为什么在主模块中使用setTimeout(0)和setImmediate()的行为未定义?

ng.*_*bie 5 event-loop race-condition node.js

采取以下来自nodejs事件循环文档的代码:

 // timeout_vs_immediate.js
    setTimeout(() => {
      console.log('timeout');
    }, 0);

    setImmediate(() => {
      console.log('immediate');
    });
Run Code Online (Sandbox Code Playgroud)

根据文档:

例如,如果我们运行以下不在I / O周期(即主模块)内的脚本,则执行两个计时器的顺序是不确定的,因为它受进程性能的约束。

为什么上述说法是正确的?是因为nodejs运行时实际上使用了多个线程来挑选必须执行的回调。

我的直觉是什么:有两个线程为setTimeout和执行回调setImmediate因此,当都可用时,这会导致竞争状态,因此输出将是不确定的。

这是对的吗 ?还是有其他原因导致不确定性?

big*_*ann 4

本质上,发生了两件事:

  1. setTimer(0..) 转换为 setTimer(1..)
  2. 在(下一个)事件循环开始之前,node/libuv 必须执行clock_gettime() 从系统获取当前时间。该系统调用所花费的时间是不确定的,因为它取决于当时的系统负载。现在,如果clock_gettime()花费的时间超过1ms,setTimer回调将运行(#),否则事件循环继续到下一阶段(##)。

    • 在情况 (#) 中,setTimeout(0,..) 回调在 setImmediate() 之前运行
    • 如果是(##),则不然。

参考: https ://github.com/nodejs/help/issues/392#issuecomment-305969168