前言
文关于
Event Loop中async/await的表现,文章中表述的观点,纯属个人的一些猜测与验证,如有不对,敬请斧正。
猜测1
由于
微任务是后加入到任务队列中的,且Promise也属于微任务,那么大胆猜测,async/await的异步任务,也属于微任务。
console.log(111);
setTimeout(() => {
console.log(222);
}, 0);
(async () => {
console.log(333);
await console.log(444);
console.log(555);
})()
.then(()=>{
console.log(666);
});
console.log(777);
// 执行结果
// 111
// 333
// 444
// 777
// 555
// 666
// 222
分析
setTimeout在 async 的上面,但是它最后执行,表明async/await的异步属于微任务;async函数,会被包装成Promise,所以console.log(6)这一块的代码,也是微任务;- 与
Promise相同,在执行async函数时,在遇到await之前,均是同步的代码;
疑问:
await 后面的代码是怎样执行的?再遇到下一个 await 又是怎样的?
猜测2
await后面的代码,async中 执行到的await后的代码是被当成一个整体来看的,这个整体属于一个微任务。
console.log(111);
setTimeout(() => {
console.log(222);
}, 0);
(async () => {
console.log(333);
await console.log(444);
console.log(555);
await console.log(666);
console.log(777);
})()
.then(()=>{
console.log(888);
});
console.log(999);
new Promise((resolve) => {
resolve();
})
.then(() => {
console.log('promise');
});
// 执行结果
// 111
// 333
// 444
// 999
// 555
// 666
// promise
// 777
// 888
// 222
分析
从当前结果看, 999 之前的应该没有疑问,都是同步代码,需要考虑的时 await 后的代码执行逻辑。
- 先将代码拆分成块:
// awaitA 代码块 --- 执行了第一个 await 后面的代码
console.log(555);
await console.log(666);
console.log(777);
// awaitB 代码块 --- 执行了第二个 await 后面的代码
console.log(777);
// async.then 代码块 --- async 的 .then 代码块,它需要等到 async 函数执行完成。
.then(()=>{
console.log(888);
});
// promise 代码块
new Promise((resolve) => {
resolve();
})
.then(() => {
console.log('promise');
});
- 分析过程:
由上面的结论,现在得到任务队列中的有四个任务:
awaitA 代码块--- 微任务;async.then 代码块--- 微任务;promise 代码块--- 微任务;setTimeout--- 宏任务;
先执行微任务:
按照 微任务 的 先进先出 规则,
执行 awaitA 代码块,打印 555, 666,此时,又遇到一个 await, 则将第二个 await 后面的代码,也就是 awaitB 代码块 追加到 微任务 中;
继续执行 微任务,此时执行 promise 代码块,打印 promise;
由于 async.then 代码块 这块比较特殊,它时等 async 执行完成后,才会被添加到队列中的,所以此时它还没有添加到队列中,所以现在执行第二个 await 后的代码块,也就是 awaitB 代码块, 此时打印 777;
当 async 函数中的代码执行完成后,async.then 代码块 的代码添加到微任务队列并执行,打印 888;
最后在执行 setTimeout,打印222.
结论:
async 在 Event Loop 中,遇到 await 之前的代码,都属于同步代码,当遇到第一个 await 后,属于 aysnc 函数中的 await 后面的所有代码,都作为一个微任务,保存到任务队列中,当执行完成同步代码后,执行任务队列中的微任务。
当执行 await 后面的 微任务 代码块时,如果内部还有 await ,后面的代码再继续被添加到 微任务队列 中,由于 微任务 的特性,所有 微任务 都执行完成后,再去执行 宏任务,所以才会出现上面的情况。