你的代码不是很具体,所以我会编一个场景。假设您有 10 个 ajax 调用,并且您想累积这 10 个 ajax 调用的结果,然后当它们全部完成时,您想做一些事情。您可以通过在数组中累积数据并跟踪最后一个完成的时间来做到这一点:
手动计数器
var ajaxCallsRemaining = 10;
var returnedData = [];
for (var i = 0; i < 10; i++) {
doAjax(whatever, function(response) {
// success handler from the ajax call
// save response
returnedData.push(response);
// see if we're done with the last ajax call
--ajaxCallsRemaining;
if (ajaxCallsRemaining <= 0) {
// all data is here now
// look through the returnedData and do whatever processing
// you want on it right here
}
});
}
注意:错误处理在这里很重要(未显示,因为它特定于您如何进行 ajax 调用)。您将需要考虑如何处理一个 ajax 调用从未完成的情况,无论是错误还是长时间卡住或长时间后超时。
jQuery 承诺
添加到我在 2014 年的回答中。如今,promise 经常用于解决此类问题,因为 jQuery$.ajax()
已经返回了一个 Promise,并且$.when()
会在一组 Promise 全部解决时通知您,并为您收集返回结果:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push($.ajax(...));
}
$.when.apply($, promises).then(function() {
// returned data is in arguments[0][0], arguments[1][0], ... arguments[9][0]
// you can process it here
}, function() {
// error occurred
});
ES6 标准承诺
如 kba 的回答中所述:如果您有一个内置原生 Promise 的环境(现代浏览器或 node.js 或使用 babeljs transpile 或使用 Promise polyfill),那么您可以使用 ES6 指定的 Promise。有关浏览器支持,请参阅此表。除了 IE,几乎所有当前的浏览器都支持 Promise。
如果doAjax()
返回一个承诺,那么你可以这样做:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
// returned data is in arguments[0], arguments[1], ... arguments[n]
// you can process it here
}, function(err) {
// error occurred
});
如果你需要将一个非承诺异步操作变成一个返回承诺的操作,你可以像这样“承诺”它:
function doAjax(...) {
return new Promise(function(resolve, reject) {
someAsyncOperation(..., function(err, result) {
if (err) return reject(err);
resolve(result);
});
});
}
然后,使用上面的模式:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
// returned data is in arguments[0], arguments[1], ... arguments[n]
// you can process it here
}, function(err) {
// error occurred
});
蓝鸟承诺
如果您使用功能更丰富的库,例如Bluebird Promise 库,那么它内置了一些额外的功能来使这更容易:
var doAjax = Promise.promisify(someAsync);
var someData = [...]
Promise.map(someData, doAjax).then(function(results) {
// all ajax results here
}, function(err) {
// some error here
});