什么是事件循环
Nodejs要处理很多事件,包括IO事件、网络事件、文件事件、,它要将这些事件分类,主要分为6类,按照1-6的顺序不断去轮询这些事件,轮询到哪个事件就执行哪个事件,那这个过程就叫做事件循环。
1. timers阶段(setTimeout)
-
I/O callbacks 该阶段不用管
-
idle, prepare 该阶段不用管
4. poll 轮询阶段,停留时间最长,可以随时离开
a. 主要用来处理I/O事件,该阶段中Node会不停询问操作系统有没有文件数据、网络数据等
b. 如果Node发现有Timer快到时间了或者有setImmediate任务,就会主动离开poll阶段
5. check阶段,主要用来处理setImmediate任务
- 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:
node17:
浏览器:
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
记笔记来做这种题