一、机制总结
(1) 事件循环机制由三部分组成:调用栈、微任务队列、消息队列;
(2) 遇到函数时,会将其压入到调用栈中,函数返回后从调用栈中弹出;
(3) js 中异步操作,如 setTimeout、setInterval等,压入到调用栈的时候,里面的消息会存储到消息队列中,等到调用栈清空之后再执行;
(4) promise、async、await 的异步操作会加入到微任务队列中,在调用栈清空时会立即执行,调用栈加入的微任务会立马执行;
(5) 微任务队列会比消息队列先执行。
二、案例分析
接下来看下面这个案例:
var p = new Promise(resolve => {
console.log(4);
resolve(5);
});
function func1() {
console.log(1);
}
function func2() {
setTimeout(() => {
console.log(2);
}, 0);
func1();
console.log(3);
p.then(resolve => {
console.log(resolve);
});
}
func2(); // 41352
(1) 创建 Promise p。此时,会立即执行 Promise 的回调函数,打印数字 4。Promise 状态变为已解析(resolved),值为 5。
(2) 调用 func2。
(3) 在 func2 内部,调用 setTimeout,它会将回调函数放入消息队列,等待执行。由于延时为 0 毫秒,回调函数会立即进入消息队列,但不会立即执行。
(4) func2 接着调用 func1,打印数字 1。
(5) func2 继续执行,打印数字 3。
(6) 在 func2 中,调用 p.then。由于 Promise p 已经解析,then 的回调函数会被放入微任务队列。
(7) func2 结束执行。在进入下一个事件循环之前,先处理微任务队列中的回调函数。执行 Promise 的 then 回调,打印数字 5。
(8) 事件循环开始处理消息队列中的回调函数。执行 setTimeout 的回调函数,打印数字 2。