是所有的节点“callback”函数可能是asynchronous?

我是一个(相对)节点新手进入系统,所有社区的热情“只是写callback,一切asynchronous和事件驱动,不用担心!” 对于单个程序中的控制stream程(或者更多节点方面,在处理大型程序中的单个请求期间的控制stream)

如果我有节点下运行下面的程序

var foo = function(){ console.log("Called Foo"); }; var bar = function(){ console.log("Called Bar"); }; var doTheThing = function(arg1, callback){ callback(); }; doTheThing(true, function() { foo(); }); bar(); 

有没有什么机会可以在后面执行foo ? 当我通过命令行在本地运行程序时,它总是

 Called Foo Called Bar 

但是我看到许多好心的布道者的警告, 不要认为你的callback会在你认为会的时候被调用 ,我不清楚他们是否只是警告我关于图书馆实施的细节,或者如果节点。当你使用函数对象作为参数时,js会做一些奇怪的事情。

不,没有机会 不是为了这个代码。

如果你正在编写你自己的函数,或者如果你有权访问代码,你不需要假设,你知道是否所有东西都是同步的,否则,如果你没有访问代码,或者没有但是阅读它,然后不,你不能假设callback将是同步的。

不过,由于两个原因,做假设是不好的做法 ,首先是因为现在同步并不意味着其他人,或者以后忘记以后不能改变,其次,因为如果全部是同步的,为什么你/他们首先使用callback? 整个callback点是为了允许asynchronous调用的可能性。 使用callback,然后像他们总是要同步,即使你知道这样的情况,使你的代码混淆,其他人进来。

没有

您的示例代码是100%同步,单线程,从上到下简单。 但那是因为你不做任何I / O,没有任何真正的asynchronous调用,不要使用process.nextTicksetTimeoutsetInterval 。 要更真实地模拟asynchronous调用,请执行以下操作:

 function fakeAsync(name, callback) { setTimeout(function () { callback(null, name); }, Math.random() * 5000); } function logIt(error, result) { console.log(result); } fakeAsync('one', logIt); fakeAsync('two', logIt); fakeAsync('three', logIt); 

运行几次,有时会看到无序的结果。

有没有什么机会可以在后面执行foo?

在你当前的代码中,没有。 虽然你的doTheThing函数有一个asynchronous函数签名(也就是说,它需要一个callback作为最后一个参数,对于一个不知道函数实现的知识的外部人员来说,它是asynchronous的),但它实际上是完全同步的, callback将被调用而不会产生到运行时。

然而

你真的没有理由给你的doTheThing代码一个asynchronous签名, 除非你愿意介绍真正的asynchronous行为doTheThing在某个时刻。 在那个时候,你有一个问题,因为foobar被调用的顺序将会翻转。

在我看来,像你这样编写代码只有两种好的方法:或者使它成为同步(最重要的是:它不依赖于I / O),这意味着你可以只需从函数返回:

 doTheThing = function(arg1){ return null }; doTheThing() foo() bar() 

或直接更改doTheThing的存根实现以包含对setImmediate的调用,即

 var doTheThing = function(arg1, callback){ setImmediate(function() { callback(); ); }; 

请注意,这也可以写成

 var doTheThing = function(arg1, callback){ setImmediate(callback); }; 

但是这只是因为在这个时候,callback没有任何参数。 第一个版本更接近你的。

只要你这样做, bar将永远在foo之前被调用,现在已经变得安全,引入asynchronousfunctiondoTheThing