问题:
在JavaScript的异步代码执行时:
-
如果遇到await,就将await执行后,后面的代码放入等待队列(因为async和await的本质还是promise的运用,返回的是一个promise对象)。
备注:async是generator的语法糖, 只是把generator的function后面的*换成了前面的async,把yield换成了await。运行原理是一样的,都是为了解决JS的异步操作问题,毕竟JS是单线程的。
-
如果遇到promise的then和catch,也同样放入等待队列,二者优先级相同,在同步代码结束后按照队列的先入先出原则执行。
-
如果遇到setTimeout的话,也是同样放在等待队列,但是是不同的等待队列,优先级低于await和promise。
代码证明:
async function async1() {
console.log("async1 start");
await async2(); // 关键点1
console.log("async1 end");
}
async function async2() {
console.log( 'async2');
}
console.log("script start");
setTimeout(function () {
// 关键点2
console.log("settimeout");
},0);
async1();
new Promise(function (resolve) {
console.log("promise1");
// 关键点3
resolve();
}).then(function () {
console.log("promise2");
});
console.log('script end');
以上代码片段的执行结果为:
>"script start"
> "async1 start"
> "async2"
> "promise1"
> "script end"
> "async1 end"
> "promise2"
> "settimeout"
解释:
----------------------------------------- 同步代码部分 --------------------------------------------
- 代码运行从同步操作
console.log("script start");
开始,遇到setTimeout直接丢到等待队列的最末端(其实是另一个优先级较低的等待队列的队首,姑且认为是promise等待队列的最末端)。 - 执行async1函数,其中的
console.log("async1 start");
为同步代码,直接输出,然后遇到了await async2
。 - 进入async2函数内部,执行其中包含的同步代码
console.log( 'async2');
,在执行过后马上将await后面的代码全部放到promise等待队列中。 - 接着寻找同步代码,发现promise中的
console.log("promise1");
为同步代码,立即执行。然后发现这个promise后面紧跟真一个then(),不要犹豫直接将这个promise放入刚刚已经存放了await的等待队列中。 - 最后一个同步代码
console.log('script end');
被找到并执行。
----------------------------------------- 异步代码部分 --------------------------------------------
现在的异步代码等待队列中,包含await函数后面的所有代码,和promise的then()
- 先执行await async2后面的代码
console.log("async1 end");
。 - 在执行promise中的then()中的resolve代码
console.log("promise2");
。 - 最后执行setTimeout代码
console.log("settimeout");
。
√到此为止所有代码执行完毕。