Javascript - 等待多个异步回调返回?

14

什么是处理多个异步回调的最佳方法/库?目前,我有类似这样的代码:

_.each(stuff, function(thing){
   async(thing, callback);
});
我需要在每个stuff元素的回调函数被触发后执行一些代码。
最干净的方法是什么?我可以使用库。

可能是重复的问题:在继续之前等待多个异步调用完成 - RMalke
6个回答

28

既然你已经在使用Underscore,你可以看一下_.after。它正好可以满足你的需求。从文档中可以看到:

after    _.after(count, function)

创建一个版本的函数,只有在第一次被调用count次后才会运行。这对于分组异步响应非常有用,其中您希望在继续之前确保所有异步调用都已完成。


13

有一个很棒的库叫做Async.js,它可以通过许多异步和流程控制工具来解决此类问题。它提供了几个forEach函数,可以帮助您对数组/对象中的每个项目运行回调。

请查看:https://github.com/caolan/async#forEach

// will print 1,2,3,4,5,6,7,all done

var arr = [1,2,3,4,5,6,7];

function doSomething(item, done) {
  setTimeout(function() {
    console.log(item);
    done(); // call this when you're done with whatever you're doing
  }, 50);
}

async.forEach(arr, doSomething, function(err) {
    console.log("all done");
});

这很不错,如果它可以为我处理链接,我可能会稍后转换。它是否比仅使用计数器(如_.after)更智能地执行某些操作? - Stefan Kendall
很酷的是,如果你想让它们一个接一个地运行,你可以使用async.forEachSerial。这给了你灵活性。对于简单的用例,计数功能非常好,并且已经内置在underscore中。试试吧! - Jamund Ferguson
我最终需要频繁地使用“series”,并且切换到异步编程显然使代码更加整洁。我也相当确定在这个过程中发现了一个回调时间问题。 - Stefan Kendall
@StefanKendall 很有趣!如果我没记错的话,如果您立即返回,可能会出现问题,这意味着您的函数不是异步的。我相信可以通过在 setTimeout(fn, 0); 中包装早期返回来解决这个问题! - Jamund Ferguson

2
我建议使用https://github.com/caolan/async。您可以使用async.parallel来完成此操作。
function stuffDoer(thing) {
    return function (callback) {
        //Do stuff here with thing
        callback(null, thing);
    }
}

var work = _.map(stuff, stuffDoer)
async.parallel(work, function (error, results) {
    //error will be defined if anything passed an error to the callback
    //results will be an unordered array of whatever return value if any
    //the worker functions passed to the callback
}

我认为在这种情况下,async.forEach和async.parallel基本上是相同的。甚至在forEach的文档中都说“它们并行执行”。不过,“parallel”这个名称更清晰明了。 - Peter Lyons
嗯,是的,在这种情况下似乎使用forEach更合适,因为它会为您处理闭包,您只需提供一个常规函数和数据列表即可。 - Peter Lyons

1

async.parallel() / async.series应该符合你的要求。你可以提供一个最终回调函数,在所有REST调用成功时执行。

async.parallel([
    function(){ ... },
    function(){ ... }
], callback);
async.series([
    function(){ ... },
    function(){ ... }
], callback);

0
有一个计数器,叫做async_count。在每次开始请求时(在循环内部),将其增加一,并让回调函数将其减少一并检查是否达到了零 - 如果是,则所有回调函数都已返回。
编辑:虽然如果我是编写此代码的人,我会链式调用请求而不是并行运行它们 - 换句话说,我有一个请求队列,并让回调函数检查队列以获取下一个要执行的请求。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接