Event Loop - msforest/notebook GitHub Wiki
大家都知道 js 是单进程单线程模式,既减少了多线程上下文切换的开销,又降低了复杂场景的难度。但是 js 并不因为单线程,性能有所下降;相反,js 使用事件循环实现类似并发的操作,我们把它叫做“异步”
预习概念
- 异步 vs 并发
- 微任务 vs 宏任务
Node.js 的事件循环
根据官网事件循环得出如下图:
Callback Queue 事件循环的每个阶段内部都含有一个 callback 队列,当运行到某个阶段时,按照 FIFO 的顺序依次执行 callback,直到队列为空才进入下一个阶段。
Microtasks 俗称“微任务”,会在主线程和事件循环的每一个阶段执行之后进入该“微任务”队列。 “微任务”包含:
- process.nextTick();
- promise.then()
也会形成一个 FIFO 队列。nextTick 优先于 promise.then
Timer 不支持传入字符串参数
- setTimeout
- setInterval
ps: 根据mdn显示,setTimeout/setInterval 使用同一个 ID 池
Pending
略
Idel,prepare
略
Poll 处理和 I/O 相关的 callback;如 fs 模块。若 poll 队列不为空,则执行;若为空,1. setImmediate 不为空,则进入下一阶段;2. setImmediate 为空,则等待队列被添加执行
Check
- setImmediate 若 poll 阶段为空而 check 队列不为空时,会执行 check 队列,而不是在 poll 阶段瞎等待
Close
略
浏览器的事件循环
macrotask(tasks)
包含执行整体的 js 代码,事件回调,XHR 回调,定时器(setTimeout/setInterval/setImmediate),IO 操作,UI render
microtask
更新应用程序状态的任务,包括 promise 回调,MutationObserver,process.nextTick,Object.observe 每个 macrotask 任务队列执行完之后都会执行 microtask 队列 ps: macrotask/microtask 类似于 callback 队列
js call stack
负责主线程的任务调度,函数回调会形成一个栈帧,帧中包含当前执行函数的参数和局部变量等上下文信息,执行完后弹出当前栈帧进行垃圾回收。call stack 是 LIFO。
参考: