【Node.js】Event Loop执行顺序详解

时间:2021-07-09 15:15:22

本文基于node 0.10.22版本

关于EventLoop是什么,请看阮老师写的什么是EventLoop

本文讲述的是EventLoop中的执行顺序(着重讲setImmediate, setTimeout/setInterval, I/O的顺序)

首先看看github上看到的nodejs eventloop 的图解, 来源于https://github.com/joyent/node/issues/6034#issuecomment-30017889

【Node.js】Event Loop执行顺序详解

(注意图中timers处process.nextTick仍可以优先于timers处执行,可能是图中有遗漏, 任何回调中设置的nextTick都会在回调结束时最优先调用,所有nextTick执行完毕才会继续EventLoop的遍历)

解释一下:

每一次EventLoop会按以下顺序遍历 timers ->poll(I/O)->check(immediates)

  • timers阶段会将达到延时的回调依次执行完,该阶段中设置的timers都不会在该次event loop中执行,即使已到达延时
  • poll阶段会将已返回数据的I/O回调依次执行完毕,该阶段设置的I/O都不会在该次event loop中执行,即使数据已经返回
  • check阶段将只执行一个最先设置的immediate回调,就跳出该阶段了
  • timers阶段若设置了I/O任务,并且在poll阶段前数据就已经返回,该I/O回调将会在该次event loop的poll阶段执行
  • timers和poll阶段若设置了immediates的回调,并且此回调是最先设置的回调,则该回调会在该次event loop的check阶段执行
setTimeout(function(){
//第一次进入event loop
console.log('setTimeout - 1');
//timers中设置的timers只会在下次event loop中执行
setTimeout(function(){
console.log('setTimeout - 2');
}, 0)
//timers中设置的io延时足够低时将在这次event loop中执行
fs.stat('file', function(){
console.log('I/O');
}) ;
//timers或poll阶段设置的immediate回调若是该immediates回调数组中的第一个,将在这次Event loop中执行
setImmediate(function(){
console.log('setImmediate');
}) ;
}, 0);

注意: 一个eventloop的时间并不确定,我们不能确定程序处于哪个阶段处于哪个eventloop,能确定的只有[同一个eventloop内的执行顺序]

送上负责nodejs的event loop部分(c++)的libuv库的介绍:http://nikhilm.github.io/uvbook/index.html

补充一下:(个人理解)

idle阶段指的是进程属于闲置状态,没有更多的事件需要处理

prepare阶段指的是进程开始阻塞(也就是同步代码开始运行)前的阶段

(刚接触nodejs,还没了解到有哪些借口可以为这两个阶段设置回调)

check阶段指的是进程阻塞完毕后的阶段