我正在查看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日志之前调用的所有函数和最终回调是肯定的吗?
答案 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
}
);