搞懂一道async await, promise, setTimeout执行顺序的前端面试题

先指明这道题是面试题的改版,原题可以看:promise、async和await之执行顺序的那点事
这道题也不是我改的,出处见:async/await 执行顺序详解

这两篇文章写的非常好,我仔细琢磨了一下,感觉受益匪浅,决定记录一下自己的理解。
不再废话,下面见题:

async function testSometing() {
    console.log("执行testSometing");
    return "testSometing";
}

async function testAsync() {
    console.log("执行testAsync");
    return Promise.resolve("hello async");
}

async function test() {
    console.log("test start...");
    const v1 = await testSometing();
    console.log(v1);
    const v2 = await testAsync();
    console.log(v2);
    console.log(v1, v2);
}

test();

var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//3
promise.then((val)=> console.log(val));

console.log("test end...")

输出结果:

1 test start...
2 执行testSometing
3 promise start..
4 test end...
5 promise
6 testSometing
7 执行testAsync
8 hello async
9 testSometing hello async


这道题最难理解的地方5和6的执行顺序,前面1~4的结果一般没有异议,如果不明白,百度一下变可以理解。
5的结果是promise的then方法里输出的,6打印的第一个await的返回结果。

下面先说一下async的await:
async 函数中可能会有 await 表达式,这会使 async 函数暂停执行,将await的结果封装成一个Promise,并等待解析完成后继续执行,
另外如果await 遇上async函数,阮一峰老师这么说明:
async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。

所以如果await遇到了 async函数,就会封装两次Promise,即:

const v1 = await testSometing();

可以理解成下面的代码:

new Promise((resolve)=> {
 resolve(Promise.resolve(testSometing()));
}).then((val)=>{
  const v1 = val
  ...
})

按照这个思路,将题目await 都替换成promise:

function testSometing() {
    console.log("执行testSometing");
    return "testSometing";
}

function testAsync() {
    console.log("执行testAsync");
    return Promise.resolve("hello async");
}

async function test() {
    console.log("test start...");
    new Promise((resolve)=> {
     resolve(Promise.resolve(testSometing()));
    }).then((val)=>{
      const v1 = val
      console.log(v1);
      new Promise((resolve)=> {
         resolve(Promise.resolve(testAsync()));
      }).then((val)=>{
          const v2 = val
          console.log(v2);
          console.log(v1, v2);
      })
    })
    
}

test();

var promise = new Promise((resolve)=> { console.log("promise start.."); resolve("promise");});//3
promise.then((val)=> console.log(val));

console.log("test end...")

执行的结果如下:

test start...
执行testSometing
promise start..
test end...
promise
testSometing
执行testAsync
hello async
testSometing hello async

大家可以和最上面的结果对比一下,哈哈!完全一样。

这道题应该算是明白了,但是我又发现一个新的问题,现在还没搞明白,请大神解答

相关推荐