JS事件循环混淆

Kua*_*uan 1 javascript v8 event-loop

我是JS事件循环的新手,我想知道是否有人可以通过js引擎如何运行这个简单的步骤:

function start(){
  setTimeout(function(){
    console.log("Timeout")
  }, 0)
  setImmediate(function(){
    console.log("Immediate")
  })
  process.nextTick(function(){
    console.log("next tick")
  })
}
Run Code Online (Sandbox Code Playgroud)

结果是:

next tick
Timeout
Immediate
Run Code Online (Sandbox Code Playgroud)

我想当JS引擎运行时,

  1. 它解析脚本,设置Timer,设置Immediate,设置nextTick队列,然后进入POLL阶段,检查是否排队等待(在这种情况下没有)
  2. 在进入CHECK阶段之前,它运行nextTick队列,打印"next tick".
  3. 移至CHECK阶段,立即运行队列,打印"立即"
  4. 循环回到TIMER阶段,打印"Timeout"

我的困惑是为什么setTimeout在立即之前打印出来?

PS,

将Timeout延迟设置为0到3或更多后,顺序为:

next tick
Immediate
Timeout
Run Code Online (Sandbox Code Playgroud)

但这仍然无法解释为什么以前的订单JS事件循环运行.

我想知道我错过了什么?

San*_*mal 5

setImmediate将函数排队在事件队列中已有的I/O,事件,回调之后.所以,在这种情况下setTimeout已经在队列中.

我想你应该再次阅读https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/.它可以回答您的所有问题.我引用了上述文件中的以下几行

setImmediate()vs setTimeout()

setImmediate并且setTimeout()是相似的,但根据它们被调用的时间以不同的方式表现.

setImmediate()设计用于在当前轮询阶段完成后执行脚本. setTimeout()安排在经过最小阈值(ms)后运行的脚本.

执行计时器的顺序将根据调用它们的上下文而有所不同.

理解 process.nextTick()

process.nextTick()从技术上讲,它不是事件循环的一部分.相反,nextTickQueue无论事件循环的当前阶段如何,都将在当前操作完成后处理.

回顾一下我们的图表,无论何时process.nextTick()在给定阶段调用,传递给的所有回调都process.nextTick()将在事件循环继续之前得到解决.这可能会产生一些不良情况,因为它允许您通过进行递归process.nextTick()调用来"饿死"您的I/O ,这会阻止事件循环到达轮询阶段.