是对Node.js的调用' async.parallel()同步?

时间:2014-02-07 15:12:47

标签: javascript node.js asynchronous async.js

我正在查看Node.js'async模块以解决问题。我已经实施了一个小测试:

var async = require("async");

function print(val) {
    console.log(val);
}

async.parallel([
    function(cb){ print(1); cb(null); },
    function(cb){ print(2); cb(null); },
    function(cb){ print(3); cb(null); },
    function(cb){ print(4); cb(null); },
    function(cb){ print(5); cb(null); }
],
    function(err) {
        if ( err ) {
            console.error(err);
            return;
        }
        console.log("Done!");
    }
);

console.log("Trulu");

我可以确定在调用async.parallel之前永远不会调用Trulu日志调用吗?换句话说,在调用Trulu日志之前调用的所有函数和最终回调是肯定的吗?

3 个答案:

答案 0 :(得分:3)

简短回答:不,它们是异步的。

答案很长:

只要您在parralel回调中执行任何异步操作,就可以在{I}后立即调用Trulu。当您致电cb时,它会宣布该函数已返回。当所有函数都返回后,它将调用最后一个回调。

因此,如果你在没有时间的情况下执行setTimeout并且每个函数都返回没有任何asynchrone,它们可能表现为同步,因为Javascript一次只运行一个单元。因为它们可能是按顺序启动的,所以它看起来好像是同步运行的。

以此为例:

var looping = true;

setTimeout(function () {looping = false;}, 1000);

while(looping) {
   ...
}

此代码永远不会离开,因为setTimeout永远不会被触发。在async.parralel中,我几乎可以肯定每个回调都将在当前单元运行完毕后执行。这意味着,在console.log("Trulu")内的任何回调之前,您始终会执行async.parralel

注意

如果您正在寻找同步事物,则不应使用名为async的模块。很明显,它将是异步

那就是说,我觉得术语async存在很大的误解。异步不是parralelism或同时发生事物的同义词。 Asynchrone,意思是“没有时间顺序”。它可以是同时的,但也可以是顺序的。要在Javascript上运行异步代码,您必须依赖于事件循环。

事件循环一次只能处理一个事件,setTimeout只是将事件放在循环上。一旦事件处理程序离开,它就会进入下一个事件,依此类推。

在您的情况下,由于您未在事件处理程序中调用cb,因此它们将被同步调用,因为它们永远不会离开当前event

答案 1 :(得分:3)

  

我可以确定在调用async.parallel完成之前永远不会调用Trulu日志调用吗?

电话本身,是的。

  

换句话说,是所有功能

我想是的,尽管文档没有提到它。但是我希望不会有任何变化,因为这可能会破坏现有的代码。

  

并且在调用Trulu日志之前调用的最终回调是肯定的吗?

没有。您不知道这些函数,当它们是异步的时,最终的回调将在Trulu之后执行。如果所有函数都是同步的,那么无论如何都不应该使用async。实际上,虽然async.js确实使用setImmediate internally所以一些回调(遗憾的是很难识别)将是“异步”,而维护者stated

  

是的,使函数异步由开发人员

决定

如果要确保始终以异步方式调用回调(Trulu之后),即使函数是同步的,也可以考虑使用A+ compliant Promises

答案 2 :(得分:1)

由于您已经使用异步,因此async会进行series调用。我认为这可能是你正在寻找的,但是警告,这很难看(因为在我看来async.js固有地造成了混乱):

async.series([
  parallel,
  function(callBack){ console.log("Trulu"); callBack(null); }
]);

function parallel(callBack){

  async.parallel([
    function(cb){ print(1); cb(null); },
    function(cb){ print(2); cb(null); },
    function(cb){ print(3); cb(null); },
    function(cb){ print(4); cb(null); },
    function(cb){ print(5); cb(null); }
  ],
    function(err) {
        if ( err ) {
            console.error(err);
            return;
        }
        console.log("Done!");
        callBack(null);
    }
  );
}

老实说,我认为异步模块通常会使javascript变得比它本身更复杂。如果你想要一个答案,告诉你如何在不使用异步模块的情况下做你想做的事情,请告诉我!

另一个更简单的解决方案是在内置到async.parallel的回调之后构建您要执行的最后一个调用:

async.parallel([
  function(cb){ print(1); cb(null); },
  function(cb){ print(2); cb(null); },
  function(cb){ print(3); cb(null); },
  function(cb){ print(4); cb(null); },
  function(cb){ print(5); cb(null); }
],
  function(err) {          
      if ( err ) {
          console.error(err);
          return;
      }
      console.log("Done!");          
      console.log("Trulu"); // Executes after all your "parallel calls" are done
  }
);