节点JS process.nextTick和setTimeout

时间:2017-04-07 01:56:56

标签: node.js settimeout event-loop

https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/阅读有关Node JS事件循环的文档之后。我试图运行此代码以了解更多信息:

//setTimeout 1
setTimeout(function A (){
    console.log('timeout 1 called!!!');
    process.nextTick(function E (){
        console.log('tick called');
    })
});
//setTimeout 2
setTimeout(function B (){
    console.log('timeout 2 called!!!');
});

结果是不可预测的,当我尝试多次运行此代码时,结果是:

timeout 1 called!!!
timeout 2 called!!!
tick called

但有时它可能是:

timeout 1 called!!!
tick called
timeout 2 called!!!

根据我的理解,这是因为process.nextTick在事件循环的每个阶段完成后运行。

因此,如果调用堆栈已完成,则会发生2种情况:

  1. NodeJS API完成解析setTimeout 1,在事件循环的定时器阶段向定时器队列添加功能A,并在NodeJS API完成解析setTimeout 2之前启动事件循环。该功能B将在函数B之前添加到nextTickQueue添加到计时器队列=>在函数A完成后,计时器队列为空(计时器阶段完成)=> nextTickQueue called =>结果是:
  2. timeout 1 called!!!
    tick called!!!
    timeout 2 called!!!
    
    1. NodeJS API完成解析setTimeout 1,在事件循环的定时器阶段向定时器队列添加功能A并且NodeJS API完成解析setTimeout 2之后,在事件循环开始之前将功能B添加到定时器队列。因此事件循环将在定时器队列中执行所有回调函数以完成定时器阶段,因此nextTickQueue将在超时1和超时2完成后解析。结果是:
    2. timeout 1 called!!!
      timeout 2 called!!!
      tick called!!!
      

      我理解对吗?你能帮我澄清一下吗? 谢谢:)。

1 个答案:

答案 0 :(得分:1)

  

根据我的理解,这是因为process.nextTick运行而发生的   事件循环的每个阶段完成后。

在每个阶段结束之前和下一阶段开始之前执行process.nextTick

该输出非确定性。您无法保证上述执行顺序。您所能做的只是根据其输出得出结论。

因此,如果调用堆栈已完成,则会发生2种情况:

  

NodeJS API完成解析setTimeout 1,将函数A添加到计时器   在事件循环的定时器阶段排队,事件循环在NodeJS之前启动   API完成解析setTimeout 2 。这就是函数E的意思   在函数B添加到timers队列之前添加到nextTickQueue队列=>   在函数A完成后,计时器队列为空(计时器阶段完成)   => nextTickQueue called =>结果是:

一旦启动你的node.js进程事件循环就开始了。一个更合适的术语是event loop moves to the nextPhase before setTimeout2 resolves

休息由于使用的技术术语很少,所以您提出的所有理由都很好。但那没关系!