私がここで誤解していることについての洞察に感謝します。私の要件は次のとおりです。
URLの配列があります。各URLのAJAXリクエストを同時に実行したいのですが、最初のリクエストが完了したらすぐに、最初のコールバックを呼び出します。次に、2番目のリクエストが完了したら、そのコールバックを呼び出します。
オプション1:
for (var i = 0; i < myUrlArray.length; i++) {
$.ajax({
url: myUrlArray[i]
}).done(function(response) {
// Do something with response
});
}
応答が正しい順序で完了する保証がないため、明らかにこれは機能しません。
オプション2:
var promises = [];
for (var i = 0; i < myUrlArray.length; i++) {
promises.push($.ajax({
url: myUrlArray[i]
}));
}
$.when.apply($, promises).then(function() {
// Do something with each response
});
これは機能するはずですが、欠点は、すべてのAJAXリクエストが完了するまで待機してから、コールバックを起動することです。
理想的には、最初のコールバックが完了したらすぐに呼び出し、次に2番目のコールバックをチェーンして、その応答が受信されるたびに(または、すでに解決されている場合はすぐに)実行し、3番目というように続けます。
配列の長さは完全に可変であり、いつでも任意の数のリクエストを含めることができるため、コールバックチェーンをハードコーディングすることはオプションではありません。
私の試み:
var promises = [];
for (var i = 0; i < myUrlArray.length; i++) {
promises.push($.ajax({
url: myUrlArray[i] // Add each AJAX Deferred to the promises array
}));
}
(function handleAJAX() {
var promise;
if (promises.length) {
promise = promises.shift(); // Grab the first one in the stack
promise.then(function(response) { // Set up 'done' callback
// Do something with response
if (promises.length) {
handleAJAX(); // Move onto the next one
}
});
}
}());
問題は、コールバックが完全にランダムな順序で実行されることです。たとえば、配列に「home.html」、「page2.html」、「page3.html」を追加した場合、応答の順序は必ずしも「home.html」、「page2.html」、「page3」になるとは限りません。 .html'。
私は明らかに、約束が機能する方法について何かを根本的に誤解しています。どんな助けでもありがたいことに感謝します!
乾杯
編集
OK、今はさらに混乱しています。このJSFiddleは、 Alnitakの回答を使用した配列とJoeFletchの回答を使用した別の配列で作成しましたが、どちらも期待どおりに機能しません。誰かがここで何が起こっているのか見ることができますか?
編集2
動作しました!以下のJoeFletchの回答に基づいて、私は次のようにソリューションを適応させました。
var i, responseArr = [];
for (i = 0; i < myUrlArray.length; i++) {
responseArr.push('0'); // <-- Add 'unprocessed' flag for each pending request
(function(ii) {
$.ajax({
url: myUrlArray[ii]
}).done(function(response) {
responseArr[ii] = response; // <-- Store response in array
}).fail(function(xhr, status, error) {
responseArr[ii] = 'ERROR';
}).always(function(response) {
for (var iii = 0; iii < responseArr.length; iii++) { // <-- Loop through entire response array from the beginning
if (responseArr[iii] === '0') {
return; // As soon as we hit an 'unprocessed' request, exit loop
}
else if (responseArr[iii] !== 'done') {
$('#target').append(responseArr[iii]); // <-- Do actual callback DOM append stuff
responseArr[iii] = 'done'; // <-- Set 'complete' flag for this request
}
}
});
}(i)); // <-- pass current value of i into closure to encapsulate
}
TL; DR: jQueryの約束がわかりません。それがなくても、機能します。:)