是所有的节点“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.nextTick
, setTimeout
或setInterval
。 要更真实地模拟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
在某个时刻。 在那个时候,你有一个问题,因为foo
和bar
被调用的顺序将会翻转。
在我看来,像你这样编写代码只有两种好的方法:或者使它成为同步(最重要的是:它不依赖于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
。