感谢您对我在这里误解的任何见解。我的要求如下:
我有一组 URL。我想同时为每个 URL 触发一个 AJAX 请求,一旦第一个请求完成,就调用第一个回调。然后,如果第二个请求完成,则调用该回调,依此类推。
选项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 请求都完成后,才会触发任何回调。
理想情况下,我应该能够在第一个回调完成后立即调用它,然后在收到该响应时链接第二个回调以执行(或者如果它已经解决,则立即执行),然后是第三个,依此类推。
数组长度是完全可变的,并且可以在任何给定时间包含任意数量的请求,因此仅对回调链进行硬编码不是一种选择。
我的尝试:
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'。
我显然从根本上误解了承诺的工作方式。任何帮助感激不尽!
干杯
编辑
好吧,现在我更困惑了。我使用Alnitak 的答案和另一个使用JoeFletch 的答案的数组制作了这个 JSFiddle,但它们都没有像我预期的那样工作!谁能看到这里发生了什么?
编辑 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 承诺,没有它们就可以工作。:)