繁体   English   中英

所有节点“回调”功能都可能是异步的吗?

[英]Are All Node “callback” Functions Potentially Asynchronous?

我是进入系统的(相对)节点新手,并且社区中的所有热情“只需编写回调,所有内容都是异步的并且是事件驱动的,不用担心!” 使我对单个程序中的控制流有些困惑(或更笼统地说,是在较大程序中处理单个请求期间的控制流)

如果我在节点下运行以下程序

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执行bar 当我通过命令行在本地运行程序时,总是

Called Foo
Called Bar

但是我看到好主意的福音派人士发出了许多警告,包括不要假设您认为回调会被调用 ,我不清楚他们是否只是在警告我有关库实现的详细信息或节点。当您使用函数对象作为参数时,js会做一些奇怪的/特殊的事情。

不,没有机会。 不适用于该代码。

如果您正在编写自己的函数,或者可以访问代码,则无需假设一切都是同步的,而是如果您无法访问代码或没有权限,则可以。尚未阅读,那么不行,您不能假设回调将是同步的。

但是,进行这样的假设是不好的做法 ,原因有两个,首先是仅仅因为它现在是同步的,就不意味着其他人,或者健忘的未来您以后不能更改它,其次,因为如果它们都是同步的,为什么您/他们是否首先使用回调? 回调的全部要点是允许异步调用的可能性。 使用回调,然后像使它们始终保持同步一样工作,即使您知道这种情况,也会使您的代码对其他任何人造成混乱。

没有

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

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在bar之后执行是否有可能?

在您当前的代码中,没有。 尽管您的doTheThing函数具有异步函数签名(即,将回调作为最后一个参数,对不知道该函数实现的局外人来说,这表明它是异步的),但它实际上是完全同步的,并且将在不产生callback情况下调用callback到运行时。

然而

您确实没有理由为您的doTheThing代码提供一个异步签名, 除非doTheThing在某个时候将真正的异步行为引入doTheThing中。 到那时,您遇到了问题,因为foobar的调用顺序将翻转。

在我看来,只有两种写代码的好方法,就像您做的那样:要么将doTheThing设置为同步(最重要的是:它将不依赖于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);
};

但这仅仅是因为此时,回调不接受任何参数。 第一个版本更接近于您所拥有的版本。

一旦执行此操作, bar将始终在foo之前被调用,现在已经可以安全地在doTheThing引入异步功能了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM