你的代码不是很具体,所以我会编一个场景。假设您有 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 Promise
添加到我在 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 标准Promise
正如 kba 的回答中所指定的:如果您有一个内置本机Promise的环境(现代浏览器或 node.js 或使用 babeljs transpile 或使用Promise polyfill),那么您可以使用 ES6 指定的Promise。请参阅此表以了解浏览器支持。几乎所有当前浏览器都支持 Promise,但 IE 除外。
如果doAjax()
返回一个Promise,那么你可以这样做:
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
});
如果您需要将非Promise异步操作变成一个返回Promise的异步操作,您可以像这样“Promise”它:
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
});
蓝鸟Promise
如果您使用功能更丰富的库,例如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
});