如何同时调用异步函数并等待所有回调?

Aze*_*edo 1 javascript node.js

在nodeJS中,如何在继续之前同时调用异步函数并等待所有回调?

在下面的示例中,我希望main all_results仅在返回时返回f1,f2并且f3完成回调()

function main(callback){
  var all_results = [];
  f1(function(results){
    all_results.push(result)
  });

  f2(function(results){
    all_results.push(result)
  });

  f3(function(results){
    all_results.push(result)
  });

  // when all 3 calls are complete:
  callback(all_results)
}


function f1(callback){
  ...
  callback(results);
}

function f2(callback){
  ...
  callback(results);
}

function f3(callback){
  ...
  callback(results);
}
Run Code Online (Sandbox Code Playgroud)

不使用承诺.

tri*_*cot 5

您无法以同步方式返回异步检索的结果.所以函数main不能返回结果.您应该坚持使用您选择的异步方法.因此,使用回调,您还应该在调用main时提供回调函数:

function main(callback){
    var all_results = [];

    function collect(results) {
        all_results.push(results);
        // when all 3 calls are complete:
        if (all_results.length === 3) callback(all_results);
    }

    f1(collect);
    f2(collect);
    f3(collect);
}
Run Code Online (Sandbox Code Playgroud)

像这样打电话:

main(function (all_results) {
    console.log(all_results);
});
Run Code Online (Sandbox Code Playgroud)

正如其他人所说,承诺会在这种情况下产生更好的代码.

如何做到承诺

假设您无法修改函数f1,f2,f3,那么您可以使用一个简单的辅助函数创建它们的promisified版本.完成后,包含ES6的方法Promise.all将完成剩下的工作,因此代码变得非常简洁.

这里是一个片段,它定义一些虚拟的职能F1,F2,F3,其使用setTimeout来获得同步的效果:

function promisify(f) {
    return new Promise(f);
}

function main(){
    return Promise.all([f1, f2, f3].map(promisify));
}

main().then(function (results) {
    console.log(results);
});

function f1(callback){
    setTimeout(function () {
        callback('result from f1');
    }, 100);
}

function f2(callback){
    setTimeout(function () {
        callback('result from f2');
    }, 500);
}

function f3(callback){
    setTimeout(function () {
        callback('result from f3');
    }, 200);
}
Run Code Online (Sandbox Code Playgroud)