2017-07-28 32 views
1

我有一個ajax查詢其次是一些函數來執行AJAX的查詢,我用的是.then()承諾回調,以執行它們:在一個循環,然後一個函數,使用他們的組合輸出

var pictures = []; 
var venues = **an array of venues** 

$.get(url).then(functionA, functionFail).then(function B); 

但泛函中,第一成功回調,包括一個循環,觸發關閉「n」個AJAX請求:

for(var i=0; i<n; i++) { 
    var venue = venues[i]; 
    var new_url = **some_url** 

    $.ajax({url: new_url, async: false}).done(function(data) { 
     var pics = data.response.photos.items; 
     pictures.push(pics[0]); 
     pictures.push(pics[1]); 
     }).fail(function() { 
     console.log('Failed!'); 
    }); 
} 

這些環狀AJAX請求填滿全球pictures陣列。圖片數組然後被函數B使用,但由於異步性質,數組不能完全填充並立即執行。

我試圖使請求與async: false同步,但它不是完全有效的(它遺漏了循環的最後一個請求)。

如何確保在所有ajax請求完成後才執行functionB?我不想使用超時,但如果沒有別的,我會回到這個。

+0

可能會添加一個計數器,每次請求成功計數並在計數器達到n時執行函數B? – yadejo

+0

@yadejo不會在這裏工作。 :) – zeo

+0

[這是我對一個類似問題的回答](https://stackoverflow.com/a/22452909/1377002)從一段時間回來,這可能會幫助你。它使用一個URL數組,每個URL用於承諾中,所有這些都傳遞給'$ .when'。 – Andy

回答

0

可以使用Promise.all,函數的代碼:

var requests = [] 
 
for(var i=0; i<n; i++) { 
 
    var venue = venues[i]; 
 
    var new_url = **some_url** 
 
    request.push(new Promise((resolve, reject) => { 
 
     $.ajax({url: new_url}).done(function(data) { 
 
      var pics = data.response.photos.items; 
 
      resolve(pics) 
 
     }).fail(function(err) { 
 
     reject(err) 
 
     console.log('Failed!'); 
 
     }); 
 
    })) 
 
} 
 

 
return Promise.all(requests)

當所有的請求都運行成功,請求整個返回值將被推到陣列,並傳遞給函數B.

+0

賓果!這種方法完美無瑕,優雅。 – zeo

1

正如你使用jQuery,它看起來像jQuery.when()可以採取多個結果,然後調用完成後,他們都解決了。

+0

這聽起來很有希望。我將不得不重構我的代碼,讓我試試這個! :) – zeo

+0

@Andy @Axnyff啊,我試過了,但對我來說這不是最好的方法。 :)問題是,這種方法需要你確切地知道你有多少個請求(用於將參數傳遞給'$ .when()')。在我的情況下,請求的數量是可變的,它不允許我傳入一個Ajax請求對象數組(這可能已經奏效!)。所以我現在只是使用同步請求和超時,儘管這是一種解決方法,並不是很優雅。 :/ – zeo

+0

難道你不能創建一個所有承諾的數組,然後jQuery.when.call(jQuery,myArray)? https://開頭計算器。com/questions/5627284 /傳入數組延遲至 – Axnyff

1

不知道這是最好的答案,但其中之一!只需計算完成請求的次數,以及全部完成時,執行您的功能。

var completed_requests = 0, 
    returned_data = []; 

for (var i=0; i<n; i++) { 
    var venue = venues[i]; 
    var new_url = **some_url** 
    var done = function(data_array) { 
     var pics = []; 
     data_array.forEach(function(data) { 
      pics = pics.concat(data.response.photos.items); 
     }); 
     }; 

    $.ajax({url: new_url}).done(function(data) { 
     completed_requests++; 
     returned_data.push(data); 
     if (completed_requests == n) { 
      done(returned_data); 
     } 
    }).fail(function() { 
     console.log('Failed!'); 
    }); 
} 

我的例子還保存來自所有請求的數據,直到你需要它爲止。

+0

我已經嘗試過,它很直觀,但不能很好地工作。 :)通過這種方法,我需要讓變量'completed_requests'的函數B'listen'達到某個值,並且在某些情況下瀏覽器可能會凍結! – zeo

+0

你不需要'聽'它!只有在請求完成時才檢查值,因爲這是completed_requests值更改的唯一時間。瀏覽器不會凍結。 –

+0

哦,我看到你修改了一些代碼 - 我會嘗試從函數內用新數據調用done()。有趣的把戲! – zeo

0

您可以自己處理循環,一次只處理venues中的一個項目。然後一個的完成後,調用一個函數來處理下一個,當會場是空的,然後打電話給你functionB

ar pictures = []; 
var venues = **an array of venues** 

$.get(url).then(functionA, functionFail); 

function functionA() { 
    var venue = venues.shift(); 
    var new_url = **some_url**; 

    $.ajax({ 
      url: new_url, 
      async: true 
      }).done(function(data) { 
      var pics = data.response.photos.items; 
      pictures.push(pics[0]); 
      pictures.push(pics[1]); 
      if(venues.length !== 0) { 
       functionA(); 
      } 
      else { 
       functionB(); 
      } 
      }).fail(function() { 
      console.log('Failed!'); 
    }); 
} 
相關問題