Nodejs:Event Loop是什么(事件循环)

84 阅读2分钟

什么是事件循环

Nodejs要处理很多事件,包括IO事件、网络事件、文件事件、,它要将这些事件分类,主要分为6类,按照1-6的顺序不断去轮询这些事件,轮询到哪个事件就执行哪个事件,那这个过程就叫做事件循环。

1. timers阶段(setTimeout)

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

  2. idle, prepare 该阶段不用管

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

a. 主要用来处理I/O事件,该阶段中Node会不停询问操作系统有没有文件数据、网络数据等

b. 如果Node发现有Timer快到时间了或者有setImmediate任务,就会主动离开poll阶段

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

  1. 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。

node10:

image.png

image.png

node17:

image.png

image.png

浏览器:

image.png

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 运行会输出什么?  选D 因为js和libuv分开运行,事件循环是一个圈,并不能确定谁先后
// A setT setIm  
// B setIm setT  
// C 出错  
// D A 或 B   
// 在浏览器执行会怎样? 选A,因为浏览器已经准备好了,所以是从timers阶段开始

面试题2:

async function async1(){  
console.log('1') // 2  
async2().then(()=>{  
console.log('2')  
})  
}  
async function async2(){  
console.log('3') // 3  
}  
console.log('4') // 1  
setTimeout(function(){  
console.log('5')  
},0)  
async1();  
new Promise(function(resolve){  
console.log('6') // 4  
resolve();  
}).then(function(){  
console.log('7')  
})  
console.log('8') // 5
// 4 1 3 6 8 2 7 5
记笔记来做这种题