【问题标题】:async parallel of API call with callback in node.jsAPI调用的异步并行与node.js中的回调
【发布时间】:2016-03-30 11:41:55
【问题描述】:

我需要等待两个 API 回调函数的任务,当任务完成后,我希望收到一个回调,这样我就可以使用来自这两个函数的数据。

我希望该函数将被并行执行...我阅读了很多关于 async.parallel 的问题,但我找不到将这些函数与 async 一起使用的方法。

当然 async 只是一个例子,如果可行,任何其他方式都可以。

对不起,我的英语不好,我希望代码更容易理解。

谢谢

var dataFunctionA = "";
var dataFunctionB = "";

var callbackFunctionA = function(err, response, data) {
  // do some work with data
  dataFunctionA = "Hello";
}

var callbackFunctionB = function(err, response, data) {
  // do some work with data
  dataFunctionB = " World!";
}

function printHelloWorld(){
   console.write(dataFunctionA + dataFunctionB);
}


APIClient.functionA(paramA, callbackFunctionA);

APIClient.functionB(paramB, callbackFunctionB);

// need to wait for the two callbacks
printHelloWorld();

【问题讨论】:

    标签: javascript node.js asynchronous callback parallel-processing


    【解决方案1】:

    使用async.parallel,您可以通过以下方式实现:

    async.parallel({
        functionA: APIClient.functionA.bind(null, paramA),
        functionB: APIClient.functionB.bind(null, paramB)
    
    }, function(error, results) {
        processCallbacks(error, results);
    });
    

    在你的函数中,完成数据处理后你应该调用传递的隐式并行回调。

    functionA(paramA, callback) {
       // data processing
       callback(null, resultFromProcessingParamA);
    }
    

    您在这里所做的是将函数对象传递给并行。此处使用对象的键,以便您可以访问结果数组。对于上面的例子,functionA的结果会保存在results.functionA中,以此类推。

    第一个参数为空(由于 .bind),然后您传递所有其他需要的参数。回调由函数之间的parallel自动传递,只有在所有函数完成后才会调用最后一个回调。

    请运行以下 sn -p 以更好地理解。

    function functionA (paramA, callback) {
      $('body').append('<p> Parallel execution of function A and waiting for 5 seconds, parameter passed: ' + paramA + '</p>');
      setTimeout(function(){
            $('body').append('<p>processed functionA</p>');
        callback(null, ++paramA);
      }, 5000);
    }
    
    function functionB (paramB, callback) {
      $('body').append('<p> Parallel execution of function B and waiting for 1 second, parameter passed: ' + paramB + '</p>');
      setTimeout(function(){
        $('body').append('<p>processed functionB</p>');
        callback(null, ++paramB);
      }, 1000);
    }
    
    function processCallbacks (results) {
      $('body').append('<p> Processing results from two functions. ParamA now is:' + results.functionA + ' and paramB now is:' + results.functionB + '</p>');
    }
    
    
    async.parallel({
      
        functionA: functionA.bind(null, 10),
        functionB: functionB.bind(null, 2)
    
    }, function(error, results) {
      console.log(results);
        if (!error) {
          processCallbacks(results);
        }
      
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/async/1.5.0/async.js"></script>
    
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

    【讨论】:

    • 我在 API 调用中得到“抛出“必须提供回调””......知道吗?谢谢
    • 因为在你的函数上你必须抛出一个回调......我现在正在编辑答案。检查一下
    • 我正在用你的例子做一些测试...... sn-p 非常好地帮助我理解 async.parallel。我不明白为什么我要修改 API 调用 :( 我不能也不想修改它。它是一个 npm 模块,它将被升级,所以我不想编辑它。我认为我应该按照作者提供的方式使用它。也许我弄得一团糟......
    • @NiuB-Daniele 在我的示例中,我没有使用 API 调用,因为我没有在 sn-p 中包含 API。当你的代码中有这个时,你将能够使用 API 调用:)
    • 很遗憾没有......我不能以这种方式使用API​​调用,我尝试了很多方法,但总是收到错误:(
    【解决方案2】:

    如果你不想使用 Promise,你可以这样做:

    var dataFunctionA = "";
    var dataFunctionB = "";
    var dataFunctionCount = 2;
    
    function checkDone() {
      dataFunctionCount--;
      if(dataFunctionCount === 0) {
    // need to wait for the two callbacks
    printHelloWorld();  
      }
    }
    
    var callbackFunctionA = function(err, response, data) {
      // do some work with data
      dataFunctionA = "Hello";
      checkDone();
    }
    
    var callbackFunctionB = function(err, response, data) {
      // do some work with data
      dataFunctionB = " World!";
      checkDone();
    }
    
    function printHelloWorld(){
       console.write(dataFunctionA + dataFunctionB);
    }
    
    APIClient.functionA(paramA, callbackFunctionA);
    
    APIClient.functionB(paramB, callbackFunctionB);

    【讨论】:

    • 它就像一个魅力,谢谢。我刚刚添加了 dataFunctionCount = 2;在 printHelloWorld() 之后;所以 checkDone() 准备好被重用(我需要多次调用这两个 API 函数)。你能告诉我同样的例子吗?
    • 这个解决方案不能很好地扩展,也不是很干净。如果您有 10、100 个要执行的功能怎么办。你会创建 100 个变量来保存它们的数据值吗?我会选择承诺或异步,如下所示
    • @AhmadAssaf 提供了使用 Promise 的可扩展解决方案。有时人们想要一个快速而肮脏的解决方案,而不需要所有的开销,而其他时候他们想要工业实力。
    猜你喜欢
    • 2017-03-19
    • 2019-07-14
    • 1970-01-01
    • 2017-03-20
    • 2023-03-04
    • 2012-09-02
    • 2015-01-22
    • 2017-03-10
    • 2013-06-19
    相关资源
    最近更新 更多