您的代码并没有十分具体,因此我举一个场景。假设您有10个ajax调用,并且您想要累加这些调用的结果,然后当它们全部完成时执行某些操作。您可以通过在数组中累积数据并跟踪最后一个完成的时间来实现它,如下所示:
手动计数器
var ajaxCallsRemaining = 10;
var returnedData = [];
for (var i = 0; i < 10; i++) {
doAjax(whatever, function(response) {
returnedData.push(response);
--ajaxCallsRemaining;
if (ajaxCallsRemaining <= 0) {
}
});
}
注意:这里的错误处理很重要(未显示,因为它与您进行ajax调用的方式有关)。您需要考虑如何处理当一个ajax调用永远不会完成的情况,无论是出现错误还是被卡住了很长时间或超时后长时间不响应。
jQuery Promises
补充我在2014年的回答。如今,Promise经常用于解决这类问题,因为jQuery的$.ajax()
已经返回了一个Promise,而$.when()
会告诉你什么时候一组Promises全部解决,并收集返回结果:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push($.ajax(...));
}
$.when.apply($, promises).then(function() {
}, function() {
});
ES6标准的Promise
正如kba所述:如果您使用具有内置原生Promise的环境(现代浏览器或node.js或使用babeljs转译或使用promise polyfill),则可以使用ES6规定的Promise。请参见此表格了解浏览器支持情况。除IE外,几乎所有现代浏览器都支持Promise。
如果doAjax()
返回一个Promise,则可以这样做:
var promises = [];
for (var i = 0; i < 10; i++) {
promises.push(doAjax(...));
}
Promise.all(promises).then(function() {
}, function(err) {
});
如果你需要将一个非Promise异步操作转换为返回Promise的操作,你可以像这样“promisify”它:
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() {
}, function(err) {
});
Bluebird Promises
如果你使用更多功能的库,例如Bluebird promise library,那么它内置了一些额外的函数来使这个过程更加容易:
var doAjax = Promise.promisify(someAsync);
var someData = [...]
Promise.map(someData, doAjax).then(function(results) {
}, function(err) {
});