请在nextTick文档中解释示例
更新 :这原来是一个非常愚蠢的问题。 在引用的例子中我只是没有注意到一些简单的事情。
我一直在寻找关于刻度和事件循环的信息,而且大多数情况下很明显,但是nextTick文档中有一个例子令我困惑。 它说:
API对于100%同步或100%asynchronous非常重要。 考虑这个例子:
// WARNING! DO NOT USE! BAD UNSAFE HAZARD! function maybeSync(arg, cb) { if (arg) { cb(); return; } fs.stat('file', cb); }
这个API是危险的。 如果你这样做:
maybeSync(true, function() { foo(); }); bar();
那么不清楚foo()还是bar()会先被调用。
第一个问题: 为什么 foo不能保证先被调用? 有一个简单的函数调用(maybeSync),一个if和cb = foo的callback函数。 我认为这条链上的某些东西(可能)是asynchronous的,把事情推到事件队列并继续执行? 我看不出有什么可能有这种效果。
第二个问题:是否有一些文件可以帮助我理解这一点?
这很简单。 如果没有arg
, foo
保证先被调用,如果有arg
, foo
保证被称为“last”。 试想一下这里的调用堆栈:
arg
存在
- maybeSync在相同的事件循环迭代中立即调用
cb
。 在相同的事件循环迭代中,也会同步调用foo
- maybeSync返回 – 所以在这种情况下
fs.stat
永远不会被调用 -
bar
在foo
完成后被调用
arg
不存在
- maybeSync调用
fs.stat
(这是asynchronous的)提供cb
作为callback - 在当前的事件循环迭代中没有更多的同步代码运行,因此调用了
bar
-
fs.stat
是完整的,它在下一个事件循环迭代中(后面的bar
)调用cb
。foo
同步执行,但这次是在另一个事件循环迭代中执行
两者都很明显。 这里的问题是,在大多数情况下,事先并不知道是否有任何arg
值(否则就没有必要),所以你可能有两种运行这个代码的情况,这使得事情变得非常复杂。
process.nextTick
在这里模仿fs.stat
asynchronous特性,所以foo
总是在下一个事件循环迭代中被调用,从而使得stream可预测。