javascript - 如何等待一组异步回调函数?

标签 javascript asynchronous

我的代码在 javascript 中看起来像这样:

forloop {
    //async call, returns an array to its callback
}

完成所有这些异步调用后,我想计算所有数组的最小值。

我怎样才能等待所有这些?

我现在唯一的想法是有一个名为done的 bool 值数组,并在第i个回调函数中将done[i]设置为true,然后说while(并非全部完成){}

编辑:我想一个可能但丑陋的解决方案是在每个回调中编辑完成数组,然后如果每个回调设置了所有其他完成,则调用一个方法,因此最后一个完成的回调将调用继续方法。

最佳答案

您的代码不太具体,所以我将编造一个场景。假设您有 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

As specified in kba's answer :如果你有一个内置了原生 Promise 的环境(现代浏览器或 Node.js 或使用 babeljs Transpile 或使用 Promise Polyfill),那么你可以使用 ES6 指定的 Promise。请参阅this table用于浏览器支持。除了 IE 之外,当前几乎所有浏览器都支持 Promise。

如果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
});
<小时/>

bluebird promise

如果您使用功能更丰富的库,例如 Bluebird promise library ,然后它内置了一些附加功能以使这更容易:

 var doAjax = Promise.promisify(someAsync);
 var someData = [...]
 Promise.map(someData, doAjax).then(function(results) {
     // all ajax results here
 }, function(err) {
     // some error here
 });

关于javascript - 如何等待一组异步回调函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48667045/

相关文章:

asynchronous - F# 使用异步返回值

javascript - 如何将此node.async代码转换为使用q?我需要返回 promise 吗?

asynchronous - 异步 mvvm 卡住 GUI

javascript - 如何使用 JavaScript 列出 DOM 节点的所有已注册事件?

javascript - 我无法使插入忽略查询

javascript - 如何从对象中获取值?

javascript - 关于 underscore.js 中的函数是异步还是同步的一些担忧

Javascript 没有将代码放在 ID div 中

javascript - 我应该如何在express.js页面布局中填充数据

javascript - 如何使这个同步递归函数异步