JS事件循环混乱

时间:2018-08-21 16:49:07

标签: 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")
  })
}

结果是:

next tick
Timeout
Immediate

我认为当JS引擎运行此代码时,

  1. 它解析脚本,设置计时器,设置即时,设置nextTick队列,然后进入轮询阶段,检查是否有任何队列(在这种情况下没有)
  2. 在进入CHECK阶段之前,它将运行nextTick队列,并打印“ next tick”。
  3. 进入CHECK阶段,运行立即队列,打印“立即”
  4. 循环回到TIMER阶段,显示“超时”

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

PS,

将超时延迟设置为0到 3 或更高后,顺序为:

next tick
Immediate
Timeout

但这仍然不能解释为什么运行先前的JS事件循环。

我想知道我错过了什么吗?

1 个答案:

答案 0 :(得分:5)

setImmediate将函数放在事件队列中已经存在的任何I / O,事件,回调后面。因此,在这种情况下,setTimeout已经在队列中。

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

setImmediate()与setTimeout()

setImmediatesetTimeout()相似,但是根据调用时间的不同,行为方式也不同。

setImmediate()设计为在当前轮询阶段完成后执行脚本。 setTimeout()计划在最小阈值(毫秒)过去后运行脚本。

定时器的执行顺序将根据调用它们的上下文而变化。

了解process.nextTick()

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

再看一下我们的图,在给定阶段中每次调用process.nextTick()时,传递给process.nextTick()的所有回调都将在事件循环继续之前得到解决。这可能会造成一些不良情况,因为它允许您通过进行递归process.nextTick()调用来“饿死”您的I / O,从而阻止了事件循环进入轮询阶段。