如何等待一组异步回调函数? [英] How can I wait for set of asynchronous callback functions?

查看:27
本文介绍了如何等待一组异步回调函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 javascript 中有类似这样的代码:

I have code that looks something like this in javascript:

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

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

After ALL of those async calls are done, I want to calculate the min over all of the arrays.

我怎么能等到所有这些?

How can I wait for all of them?

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

My only idea right now is to have an array of booleans called done, and set done[i] to true in the ith callback function, then say while(not all are done) {}

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

edit: I suppose one possible, but ugly solution, would be to edit the done array in each callback, then call a method if all other done are set from each callback, thus the last callback to complete will call the continuing method.

提前致谢.

推荐答案

你的代码不够具体,所以我会编一个场景.假设您有 10 个 ajax 调用,并且您想累积这 10 个 ajax 调用的结果,然后当它们全部完成时,您想要做一些事情.您可以通过在数组中累积数据并跟踪最后一个完成的时间来做到这一点:

You haven't been very specific with your code, so I'll make up a scenario. Let's say you have 10 ajax calls and you want to accumulate the results from those 10 ajax calls and then when they have all completed you want to do something. You can do it like this by accumulating the data in an array and keeping track of when the last one has finished:

手动计数器

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 调用永远不会完成的情况,要么出现错误,要么卡住很长时间,或者很长时间后超时.

Note: error handling is important here (not shown because it's specific to how you're making your ajax calls). You will want to think about how you're going to handle the case when one ajax call never completes, either with an error or gets stuck for a long time or times out after a long time.

jQuery 承诺

添加到我在 2014 年的回答中.如今,由于 jQuery 的 $.ajax() 已经返回了一个 promise 并且 $.when() 会在一组 promise 全部解决时通知你,并会为你收集返回结果:

Adding to my answer in 2014. These days, promises are often used to solve this type of problem since jQuery's $.ajax() already returns a promise and $.when() will let you know when a group of promises are all resolved and will collect the return results for you:

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 的回答中所述:如果您的环境内置了本机承诺(现代浏览器或 node.js).js 或使用 babeljs transpile 或使用 promise polyfill),那么您可以使用 ES6 指定的 promise.有关浏览器支持,请参阅此表.几乎所有当前浏览器都支持 Promise,但 IE 除外.

As specified in kba's answer: if you have an environment with native promises built-in (modern browser or node.js or using babeljs transpile or using a promise polyfill), then you can use ES6-specified promises. See this table for browser support. Promises are supported in pretty much all current browsers, except IE.

如果 doAjax() 返回一个 promise,那么你可以这样做:

If doAjax() returns a promise, then you can do this:

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
});

<小时>

如果你需要将一个非承诺的异步操作变成一个返回承诺的异步操作,你可以像这样承诺"它:


If you need to make a non-promise async operation into one that returns a promise, you can "promisify" it like this:

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 库,则它内置了一些额外的功能,使这更容易:

If you use a more feature rich library such as the Bluebird promise library, then it has some additional functions built in to make this easier:

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

这篇关于如何等待一组异步回调函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆