你的代码不太具体,所以我会编一个场景。假设您有 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 年的答案。自从 jQuery 出现以来,现在经常使用 Promise 来解决此类问题$.ajax()
已经返回一个承诺并且$.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 的回答中所指定的 https://stackoverflow.com/a/33813793/576767:如果你有一个内置了原生 Promise 的环境(现代浏览器或 Node.js 或使用 babeljs Transpile 或使用 Promise Polyfill),那么你可以使用 ES6 指定的 Promise。看这张桌子 http://caniuse.com/#feat=promises用于浏览器支持。除了 IE 之外,当前几乎所有浏览器都支持 Promise。
If 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
});
蓝鸟的承诺
如果您使用功能更丰富的库,例如蓝鸟承诺图书馆 http://bluebirdjs.com/docs/api-reference.html,然后它内置了一些附加函数以使这更容易:
var doAjax = Promise.promisify(someAsync);
var someData = [...]
Promise.map(someData, doAjax).then(function(results) {
// all ajax results here
}, function(err) {
// some error here
});