任务队列——两句话,十四个字

796 阅读2分钟

总结

宏中有微,先微再宏。

遇到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 的本质是对 fulfilledPromise 进行解构,简单来说就是直接拿到 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");

结语

今天刷文章对这块突然有了开悟的感觉,花了点时间研究了一下,最后得到了这两句话,十四个字。现在就在这里分享出来了。