阅读 2247

JS异步--async,await,promise,setTimeout 执行顺序

问题:

在JavaScript的异步代码执行时:

  1. 如果遇到await,就将await执行后,后面的代码放入等待队列(因为async和await的本质还是promise的运用,返回的是一个promise对象)。

    备注:async是generator的语法糖, 只是把generator的function后面的*换成了前面的async,把yield换成了await。运行原理是一样的,都是为了解决JS的异步操作问题,毕竟JS是单线程的。

  2. 如果遇到promise的then和catch,也同样放入等待队列,二者优先级相同,在同步代码结束后按照队列的先入先出原则执行。

  3. 如果遇到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"
复制代码

解释:

----------------------------------------- 同步代码部分 --------------------------------------------

  1. 代码运行从同步操作console.log("script start");开始,遇到setTimeout直接丢到等待队列的最末端(其实是另一个优先级较低的等待队列的队首,姑且认为是promise等待队列的最末端)。
  2. 执行async1函数,其中的console.log("async1 start");为同步代码,直接输出,然后遇到了await async2
  3. 进入async2函数内部,执行其中包含的同步代码console.log( 'async2');,在执行过后马上将await后面的代码全部放到promise等待队列中。
  4. 接着寻找同步代码,发现promise中的console.log("promise1");为同步代码,立即执行。然后发现这个promise后面紧跟真一个then(),不要犹豫直接将这个promise放入刚刚已经存放了await的等待队列中。
  5. 最后一个同步代码console.log('script end');被找到并执行。

----------------------------------------- 异步代码部分 --------------------------------------------

现在的异步代码等待队列中,包含await函数后面的所有代码,和promise的then()

  1. 先执行await async2后面的代码console.log("async1 end");
  2. 在执行promise中的then()中的resolve代码console.log("promise2");
  3. 最后执行setTimeout代码console.log("settimeout");

√到此为止所有代码执行完毕。

关注下面的标签,发现更多相似文章
评论