2014-02-07 38 views
1

我正在看看Node.js'async模块来解决问题。我实现了一个小测试:是否调用Node.js的async.parallel()同步?

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日志之前调用的最终回调函数?

+1

这不会回答你的问题,我是知道的,但我想说你可以把你的东西包装在一个承诺中,以确保它 – Sprottenwels

+0

我想如果你想确保它是在回调之后,你可以让你的函数在回调中写入日志。但是我没有看到它和完成之间的区别!日志 – CubanAzcuy

+0

如果你被困在async.js中,它有一个系列的方法可以做你想做的事情。 –

回答

3

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

电话本身,是的。

换句话说,是所有功能

我想是这样的,虽然文档不提它。然而,我希望不会有任何改变,因为这可能会破坏现有的代码。

以及在Trulu日志被调用之前调用的最终回调是否可靠?

不知道函数,当它们是异步的时候,最后的回调将在Trulu之后执行。如果所有功能都是同步的,则不应使用async。事实上,虽然async.js确实使用setImmediateinternally所以一些回调(遗憾的是难以确定)将“asynchronified”,但维护者stated

是,使得功能异步留给了开发商

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

+0

我的第一个想法是你错了,但是所有的调用都是同步的,所以'Trulu'在'Done!'之后被调用。 +1 – A1rPun

3

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

龙答:

只要你做任何事情异步的,parralel回调里面,你可以期望Trulu得到立刻之后被调用。当您致电cb时,它会通知该函数返回。当所有函数都返回时,它会调用最后一次回调。

所以出于这个原因,如果你没有时间做setTimeout,并且每个函数都返回时没有任何异步,它们可能表现得像同步一样,因为Javascript一次只运行一个单元。由于它们可能是按顺序启动的,它看起来好像是同步运行。

拿这个作为一个例子:

var looping = true; 

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

while(looping) { 
    ... 
} 

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

注意

如果你正在寻找做同步的东西,你不应该使用一个叫做异步模块。很显然,这将是异步。

这就是说,我觉得对于术语async有一个很大的误解。异步不是同步或同时存在的事物。 Asynchrone,只是意味着“没有及时下单”。它可能是同步的,但也可能是顺序的。要在Javascript上运行异步代码,您必须依赖事件循环。

事件循环一次只能处理一个事件,setTimeout只是将事件放在循环中。只要事件处理程序离开,它就会进入下一个事件等等。

就你的情况而言,由于你没有在事件处理程序中调用cb,所以它们将被同步调用,因为它们从不离开当前的event

+1

他们似乎不是与[他正在讨论的异步库]异步(https://github.com/caolan/async)(奇怪),除非函数本身执行异步操作。无论是实验还是查看代码,都没有表明这些函数实际上是并行运行的,除非这些函数本身执行某些异步操作。例如,'async.parallel'同步调用函数*,但我猜测他们会做异步工作。坦率地说,这似乎很奇怪 –

+0

@ T.J.Crowder是的,我知道我在解释它 –

+0

@ T.J.Crowder:JS无法并行运行同步函数,所以你会期望:-) – Bergi

1

由于您已经使用了异步,因此异步调用了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 
    } 
); 
+0

你可以请解释如何做到这一点没有异步? – user3248186