Skip to main content

Node.js 的 EventLoop 是什么?

背景知识

Event Loop、计时器、nextTick - 掘金

Node.js 将各种函数(也叫任务或回调)分成至少 6 类,按先后顺序调用,因此将时间分为六个阶段:

  1. timer 阶段(setTimeout)

  2. I/O callbacks 该阶段不用管

  3. idle,prepare 该阶段不用管

  4. poll 轮询阶段,停留时间最长,可以随时离开

  5. check 阶段,主要处理 setImmediate 任务

  6. close callback 该阶段不用管

Node.js 会不停的从 1 ~ 6 循环处理各种事件,这个过程叫做事件循环(Event Loop)。

nextTick

process.nextTick(fn) 的 fn 会在什么时候执行呢?

在 Node.js 11 之前,会在每个阶段的末尾集中执行(俗称队尾执行)。

在 Node.js 11 之后,会在每个阶段的任务间隙执行(俗称插队执行)。

浏览器跟 Node.js 11 之后的情况类似。可以用 window.queueMicrotask 模拟 nextTick。

Promise

Promise.resolve(1).then(fn) 的 fn 会在什么时候执行?

这要看 Promise 源码是如何实现的,一般都是用 process.nextTick(fn) 实现的,所以直接参考 nextTick。

async / await

这是 Promise 的语法糖,所以直接转为 Promise 写法即可。

面试题 1:

setTimeout(() => {
console.log('setTimeout')
})

setImmediate(() => {
console.log('setImmediate')
})
// 在 Node.js 运行会输出什么?
// A setT setIm
// B setIm setT
// C 出错
// D A 或 B
// 在浏览器执行会怎样?

//A 或 B

面试题 2:

async function async1(){
console.log('1')
async2().then(()=>{
console.log('2')
})

}
async function async2(){
console.log('3')
}
console.log('4')
setTimeout(function(){
console.log('5')
},0)
async1();
new Promise(function(resolve){
console.log('6')
resolve();
}).then(function(){
console.log('7')
})
console.log('8')

微任务队列(间隙插队):async2#then、promise#then

宏任务对列(最后执行):setTimeout

最终执行:4 1 3 6 8 后面为异步队列 2(async2#then) 7(omise#then) 5(setTimeout)