在该循环之后,如何使用循环内进行的 ajax 调用的结果?

How can I use the results of ajax calls, made inside a loop, after that loop?

我已经阅读了一些关于 deferred 和 promises 的内容,但我仍然不知道如何管理它。

for(...){//we don't know the number of ajax calls
   $.ajax({...});
}

if(all the ajax call we made are done){...}

重点是我需要保持"ajax.async = true".

传统方式:

解决这个问题的传统方法是将承诺添加到数组中,然后使用 $.when.apply

将它们一起计算
var promise = [];
for (var i = 0; i < 6; i++){
    promise.push(delay(10-i, $('#' + i)));
}
$.when.apply($, promise).done(function(){
    alert("All done");
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/rgj0bx95/1/

使用返回值:

因为你想保留这些值,所以你可以使用 arguments 数组访问它们:

var promise = [];
for (var i = 0; i < 6; i++){
    promise.push(delay(6-i, $('#' + i)));
}
$.when.apply($, promise).done(function(){
    $('body').append("All done!");
    for (var i = 0; i < arguments.length; i++){
        $('body').append(arguments[i]).append("<br/>");
    }
});

示例:

下面的例子使用了一个简单的函数,returns 一个承诺,使用一个计时器,来模拟 ajax 调用。它清楚地表明即使承诺按 "random" 顺序完成(只是为了演示),该建议仍然有效:

JSFiddle: http://jsfiddle.net/TrueBlueAussie/rgj0bx95/5/

备注:

  • 值按调用顺序返回,而不是完成顺序。

其他方法

我发现的小技巧:您可以与 $.when 并行链接承诺,而不必使用承诺数组:

var promise;   // Undefined also means a resolved promise to $.when
for(...){//we don't know the number of ajax calls
   promise = $.when(promise, $.ajax({...}));
}
promise.done(function(){
   alert("All done");
});

备注:

  • 我在看到有人使用 promise = promise.then(newpromise)
  • 按顺序链式承诺后想出了这个
  • 缺点是它会在幕后创建额外的 promise 对象,并且最后传递的任何参数都不是很有用(因为它们递归地嵌套在其他对象中)。如果你不需要参数,它简短。

您将在下文中注意到 fiddle 结果是嵌套的,并且顺序与您希望的相反。同样,此技术仅在您 想要 promise 的结果时才有用(这对于并行操作来说很常见)。

总结: $.when 技术仅在您不关心结果值时才有用。

JSFiddle: http://jsfiddle.net/TrueBlueAussie/rgj0bx95/9/