总结
宏中有微,先微再宏。
遇到await,后续为微。
就这两句话,14个字+一个单词,就足以说明整个任务队列。
如果你理解了,你就可以关闭本篇文章了。
这一篇文章不会详细解释整个任务队列,而是对我自己的理解作为一个总结。
因为我个人对详细了解前因后果不感兴趣,所以只会用自己的最简单的理解来描述。
JavaScript 运行机制详解可以参考阮一峰老师的【这篇文章】。
拆解
宏中有微,先微再宏
这个是 MDN 上对微任务的一个描述。大意是切换至下一任务(宏任务)之前,会清空微任务队列。
所以,每一个宏任务都拥有自己的微任务队列,只有自己所有微任务都执行完毕的情况下,才会切换至下一个宏任务。
下图是一段测试代码,可以看到,无论以什么方式,添加多少个微任务,所有微任务都会执行完才会执行 setTimeout 中的逻辑。
微任务执行顺序
每遇到 then 就添加至微任务队列。当这个 then 里的代码执行完毕,其下一个 then 才会被添加至微任务队列中。
这里我用一小段代码来解释。
console.log(1)
new Promise((res, rej) => {
console.log(2)
// 打印完毕,resolve 的 then 添加至微任务队列。6的部分不管
Promise.resolve().then(() => { // 第一个执行的微任务
console.log(4)
// 执行完毕,添加后续 then 至微任务队列
}).then(() => {
console.log(6)
})
return res()
// 创建完毕,后续 then 添加至微任务队列
}).then(() => { // 第二个执行的微任务
console.log(5)
// 执行完毕,添加后续 then 至微任务队列
}).then(() => {
console.log(7)
})
console.log(3)
// 执行完毕,开始执行微任务
(可能这里要录一小段视频来解释了)
遇到 await,后续为微
async 的本质是将方法的返回值包装成 Promise 对象。
而 await 的本质是对 fulfilled 的 Promise 进行解构,简单来说就是直接拿到 then 里获取到的参数。
而在整个任务队列中的表现则是下面效果。这里我直接放代码了,执行结果与代码中的数字顺序一致。
async function async1() {
console.log("1");
await async2();
console.log("5");
}
async function async2() {
console.log("2");
}
async1();
setTimeout(() => {
console.log("7");
}, 0);
new Promise(function (resolve) {
console.log("3");
resolve();
}).then(function () {
console.log("6");
});
console.log("4");
结语
今天刷文章对这块突然有了开悟的感觉,花了点时间研究了一下,最后得到了这两句话,十四个字。现在就在这里分享出来了。