nodejs事件循环
nodejs中Event Loop
- timer - setTimeout和setInterval回调函数执行阶段
- pending callbacks - OS级别的回调,例如TCP链接错误等
- idle/prepare - nodejs内部使用
- poll - 各种非timer阶段的回调函数
- check - setImmediate()的回调函数
- close - 注册close事件的回调函数
process.nextTick以及Microtask
nextTick以及Microtask中的回调函数会在node初始化后进入事件循环前执行,在此过程中回清空nextTick和微任务队列中的任务,另外值得注意的是nextTick优先级高于微任务,我们看到有些文章将nextTick回调算入微任务。在此过程中会不断迭代nextTick和微任务队列直到清空为止,因此如果递归向两个队列中添加任务会导致“事件循环饥饿”。
在进入事件循环后,nextTick和微任务队列执行出现在每个回调函数执行结束后(注意此特性跟node版本有关,node v11.15.0之前是在每个阶段执行结束后才进入微任务对列迭代执行)。
poll阶段
进入poll阶段有两种情况:
- 如果poll队列不为空,则迭代执行直到os限制的最大时间片用完或者执行完队列
- 如果poll队列为空,则查看immediate队列,如果有任务则进入check阶段,另外每当队列为空时,node会检测timer队列中是否有任务,如果timer有新的任务则会通过check阶段再进入timer阶段。如果poll为空且immediate和timer队列为空则会阻塞在此阶段。
浏览器中事件循环
浏览器中分为任务队列和微任务队列,执行流程为:
- 从任务队列取一个任务执行
- 判断微任务队列是否为空,迭代执行清空微任务队列
- 任务队列和微任务队列结束后执行渲染任务
注意js执行和layout和paint在主线程执行,因此js的执行会阻塞渲染任务。
有哪些微任务?
- promise.then
- MutationObserver
requestAnimationFrame,setTimeout,setInterval方法为宏任务。