Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript NodeJs异步编程-协调并行调用_Javascript_Node.js_Asynchronous_Callback - Fatal编程技术网

Javascript NodeJs异步编程-协调并行调用

Javascript NodeJs异步编程-协调并行调用,javascript,node.js,asynchronous,callback,Javascript,Node.js,Asynchronous,Callback,我指的是关于协调NodeJs中的并行调用的nodetuts教程。 有些事情我需要你的帮助来理解 callback1、callback12、callback3是需要并行执行的函数。每个人都需要自己的时间来执行 但它们的结果将按各自的顺序存储在结果数组中 [resultofcallback1, resultofcallback2, resultofcallback3] 如前所述,最终回调的唯一约定是只执行一次并按正确顺序显示结果。 为此,我们有一个名为back的布尔值,以确保它只执行一次 mod

我指的是关于协调NodeJs中的并行调用的nodetuts教程。

有些事情我需要你的帮助来理解

callback1、callback12、callback3是需要并行执行的函数。每个人都需要自己的时间来执行

但它们的结果将按各自的顺序存储在结果数组中

[resultofcallback1, resultofcallback2, resultofcallback3]
如前所述,最终回调的唯一约定是只执行一次并按正确顺序显示结果。 为此,我们有一个名为back的
布尔值,以确保它只执行一次

module.exports = function composedCall(args, cb){

  var pending = 0;
  var results = [];
  var calledBack = false;

  callback1(args,handleResult());
  callback2(args,handleResult());
  callback3(args,handleResult());

  function handleResult(){
    var order = pending;
    pending ++;
    return function(err, result){
      pending --;
      if(err){
        callback(err);
      }else{
        results[order] = result;
        if(!pending){
          callback(null, results);
        }
      }
    }
  }
  function callback(err, value){
    if(! calledBack){
      calledBack = true;
      cb(err, value)
    }
  }
}


function callback1(args ,callback){
  setTimeout(callback, randomTimeout(), null, 1);
}

function callback2(args ,callback){
  setTimeout(callback, randomTimeout(), null, 2);
}
function callback3(args ,callback){
  setTimeout(callback, randomTimeout(), null, 3);
}

//utils
function randomTimeout(){
  return Math.floor(Math.random() * 1e3);
}

function randomValue(){
  return Math.floor(Math.random() * 1e10);
}
请参阅下面的代码

我的论点是在执行回调1时。 在
handleResult
内部:
pending=0
order=0,pending增加到1
假设此回调执行时间最短

在该handleResult的返回函数内部,挂起的
值递减
这使得
挂起0
。假设此时没有其他回调
(callback1,callback2)
达到其handlResult函数,因此挂起仍然为0。因此,这个if(!pending)断言和最终回调被称为
callBack(null,results)
只输出一个结果,如
[resultToCallback1',,'']
,其余两个为空,因为最终回调只应调用一次

module.exports = function composedCall(args, cb){

  var pending = 0;
  var results = [];
  var calledBack = false;

  callback1(args,handleResult());
  callback2(args,handleResult());
  callback3(args,handleResult());

  function handleResult(){
    var order = pending;
    pending ++;
    return function(err, result){
      pending --;
      if(err){
        callback(err);
      }else{
        results[order] = result;
        if(!pending){
          callback(null, results);
        }
      }
    }
  }
  function callback(err, value){
    if(! calledBack){
      calledBack = true;
      cb(err, value)
    }
  }
}


function callback1(args ,callback){
  setTimeout(callback, randomTimeout(), null, 1);
}

function callback2(args ,callback){
  setTimeout(callback, randomTimeout(), null, 2);
}
function callback3(args ,callback){
  setTimeout(callback, randomTimeout(), null, 3);
}

//utils
function randomTimeout(){
  return Math.floor(Math.random() * 1e3);
}

function randomValue(){
  return Math.floor(Math.random() * 1e10);
}
这是进行并行调用的正确方法吗
我错过什么了吗?

你可以随时使用异步并行或类似的东西

对于手动实现,您可以执行以下操作之一:

1-长轮询已完成任务的数量。如果#已完成任务数==总#任务数=>最终回调

2-在每次回调结束时,发送一个“我完成”信号,并检查“我完成”信号的数量。如果“我完成了”信号的数量等于任务总数=>最终回调

看起来你要用第二种方法。检查您的代码,我看您没有遗漏任何方面,但您有一个大问题:

如果第一个任务在注册第二个任务之前完成,则只能使用第一个任务的结果执行最终回调。

重申:你注册任务的方式带来了竞争条件,这在很大程度上取决于你从随机超时中滚到足够高的位置,这样你就可以在你注册的任务全部完成之前注册所有任务

建议修复:在成功注册所有任务之前,不要启动任何任务。


另外:如果您从0开始挂起并执行order=pending,那么当您注册了3个任务但没有一个任务完成时,您将得到一个pending=2,并且在第二个任务完成且第三个任务仍在进行时,您将执行最后的回调。

您缺少的是调用的是
handleResult()
同步,因此您描述的场景永远不会发生。在执行第一个异步函数之前,Pending将增加3倍。请记住,
setTimeout
s不会调用
handleResult()
。他们将调用函数
handleResult()
return。这些函数将被异步执行,
handleResult()
被同步执行以生成它们。好了,现在它有意义了。很抱歉,我严重错过了那一点。如果callback1的setTimwout设置为0会怎么样。那会有什么不同吗?我知道这是回电话,只是好奇而已!setTimeout始终调用其回调异步,即使它设置为0。它只会在下一个滴答声中调用它。
setTimeout
process.nextTick
之间的区别在于
setTimeout
处理所有异步事件,包括网络和磁盘io进程
process.nextTick
是在所有其他事件之前处理的,因此如果您在无限循环中调用
process.nextTick
,您可能会阻止所有其他进程(我发现这很难理解为什么我的数据包从未发送出去),谢谢。这真的很有帮助。