概念:
event loop : 是一个执行模型,在不同地方有不同实现,所以浏览器和nodejs基于不同技术实现了各自的event loop
宏队列:tasks
- setTimeout
- setInterval
- setImmediate(node)
- requestAnimationFrame(浏览器)
- I/O
- UI rendering (浏览器)
微队列:jobs
- process.nextTick(node)
- Promise
- Object.observe
- MutationObserver
浏览器的EventLoop:
- 执行全局同步代码
- 全局同步代码执行完成后,调用栈stack清空
- 从微队列 microtask queue 中取出队首的微任务放进stack中执行
- 继续 取微任务队列队首的微任务执行,直到把微任务队列清空(如果执行微任务时又产生新的微任务,也会在此周期被调用执行)
- 执行完毕后,调用栈stack清空
- 从宏队列 macrotask queue中取队首的宏任务 放进stack中执行
- 执行完毕后,调用栈stack清空
- 重复3~7步
- ……
归纳:
- 微队列每次执行都会清空队列
- 宏队列每次只执行队首的一个宏任务,执行完就再进入微任务队列执行。
- UIrendering执行的时机是由浏览器自行判断决定,但是他的执行时机一定是在 清空微任务之后,下一个宏任务之前。
console.log(1);
setTimeout(() => {
console.log(2);
Promise.resolve().then(() => {
console.log(3)
});
});
new Promise((resolve, reject) => {
console.log(4)
resolve(5)
}).then((data) => {
console.log(data);
})
setTimeout(() => {
console.log(6);
})
console.log(7);
// 1 4 7 5 2 3 6
NodeJs的Event Loop:
node 的EventLoop 是基于libuv实现的。
libuv的结构图:
NodeJS 执行宏队列的回调任务:
每个阶段都有一个执行回调的队列(实际上可能不是队列)。当Event Loop进入到某个阶段时,就会将该阶段的回调拿出来执行,直到队列为空(实际上会复杂一些)
六个阶段:
- timers阶段:这个阶段执行setTimeout和setInterval预定的callback
- I/O callback阶段:执行除了close事件的callbacks、被timers设定的callbacks、setImmediate()设定的callbacks这些之外的callbacks
- idle, prepare阶段:仅node内部使用
- poll阶段: 最重要的阶段,执行I/Ocallback,获取新的I/O事件,适当的条件下node将阻塞在这里。
- check阶段:执行setImmediate()设定的callbacks
- close callbacks阶段:执行socket.on('close', ....)这些callbacks
poll阶段(轮询阶段):
- 当timer到达指定时间后,执行指定的timer回调
- 处理poll队列的事件
当进入poll阶段,且没有timers被调用时
- 如果poll队列不为空,那么Event Loop将同步的执行poll队列里面的callback,直到队列为空或者是执行的callback数量达到上限。
- 如果poll队列为空,又分为两种情况:
- 如果脚本调用了setImmediate(),EventLoop将会结束poll阶段并且进入到check阶段执行setImmediate()的回调
- 如果脚本没有setImmediate()调用,那么EventLoop将会等待回调呗添加进队列,然后立即执行它们。
- 一旦poll队列为空,EventLoop会检查timers,如果有timers已经到达时间,那么EventLoop会回到Timer阶段去执行(进入到下一次tick)
Nodejs中的微任务:
- Next Tick Queue: 使用process.nextTick()添加的回调。
- MicroTask Queue: 包含一些microtasks比如resolved promise callbacks。
在EventLoop完成一个阶段,到达另一个阶段前,都会去执行微任务,知道微任务的两个队列清空,才会进入到下一个阶段。
这两个微任务队列也有先后:NextTickQueue优先级高于MicroTaskQueue。
?
来源:
一次弄懂Event Loop(彻底解决此类面试问题) - 知乎
https://segmentfault.com/a/1190000016278115
|