这个async/await符合我这个神搓搓的人欸,跟着我来探索一下他的输入输出吧

175 阅读3分钟

理解async/await的关键所在是理解await的运行逻辑。首先各位同学脑海中需要有一个概念是,async/await仅仅是一个语法糖,不具有任何额外扩充的功能。 换句话说:所有能使用async/await语法的地方都能使用Promise来代替 下文将会把async/await与不同形式的JavaScript代码组合在一起,让我们来一起观察他的执行逻辑吧!

Promise + async/await

function m1() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(1);
    }, 1000)
  });
}

async function m2() {
  const res = await m1()
  console.log(res)
}
m2()

这是最常见的场景,await 会等待Promise的状态改为fullfilled

  1. 如果成功,那么会将async函数剩余任务推入到微任务队列await后续的代码将变成:
async function m2() {
  Promise.resolve(m1()).then((res)=>{
    console.log(res)
  })
}
  1. 如果失败,那么剩余任务不会被推入微任务队列执行,它会返回Promise.reject(err)
async function m2() {
  Promise.reject(err)
}

最后的答案是:

1

我们来一道面试题

小面试题

async function test() {
  console.log(1);
  await console.log(2);
  console.log(3);
}
console.log(4);
test()
console.log(5);

答案:

await如同他的语意,就是在等待,等待右侧的表达式完成。此时的await会让出线程,阻塞async内后续的代码,先去执行async外的代码。等外面的同步代码执行完毕,才会执行里面的后续代码。就算await的不是promise对象,是一个同步函数,也会等这样操作

41253

普通的值 + async/await

即使await右边非函数,只是一个普通的数值,但它本质上是将其转化为 Promise.resolve(),所以会返回一个成功的promise。我们通过几个题来仔细研究一下

有async和await的情况下打印什么

async function m1() {
  return await 1
}
console.log(m1())

答案

image.png

有async没有await的情况下打印什么

async function m1() {
  return 1
}
console.log(m1())

答案

image.png

这个await究竟是把他后面的数字进行了什么处理呢? 其实就是下面这个样子

async function m2() {
  return await 3
}

上述等于

async function m2() {
  return Promise.resolve(2)
}

await+普通函数

如果await 右边是一个函数,它会立刻执行这个函数,而且只有当这个函数执行结束后(即函数完成)!才会将async剩余任务推入微任务队列。 我们来看一道小demo:

function m1() {
  console.log("我是m1")
  return 1
}
async function m2() {
  console.log("我是m2")
  const res = await m1()
  console.log("我是m2的中执行了m1()后的结果", res)
  return res
}
console.log("我是外面的m2", m2())

看着大概能猜出来答案是不,我们把他转换一下然后在观察

function m1() {
  console.log("我是m1")
  return 1
}
function m2() {
  console.log("我是m2")
  return Promise.resolve(m1()).then((res) => {
    console.log("我是m2的中执行了m1()后的结果", res)
  })
}
console.log("我是外面的m2", m2())

答案为:

image.png

你有没有发现其实await是把他右边的函数立即执行了里面的函数,然后把他下面的函数存入then之中。而我们都知道的是,then函数内部的代码都将被推入微队列之中。 因此显而易见,这就是await在面对普通函数时的处理逻辑。


如上所述,我将上述所有的可能作了一个小例题出来,大家可以参考着答案研究一下

小例题

    async function m1() {
        return 1;
    }
    function m2() {
        return Promise.resolve(2);
    }
    function m3() {
        return new Promise((resolve, reject) => {
            resolve(3);
        });
    }
    async function m4() {
        return Promise.resolve(4);
    }
    async function m5() {
        return new Promise((resolve, reject) => {
            resolve(5);
        });
    }
    let res6;
    async function m6() {
        res6 = await m1();
        return res6
    }
    let res7;
    async function m7() {
        res7 = m1();
        return res7
    }
    console.log("m1()", m1())
    console.log("m2()", m2())
    console.log("m3()", m3())
    console.log("m4()", m4())
    console.log("m5()", m5())
    console.log("m6()", m6(), res6)
    console.log("m7()", m7(), res7)

以下是答案哟

image.png

从一道让我失眠的 Promise 面试题开始,深入分析 Promise 实现细节

不看后悔,async和await详解

我终于搞懂了async/await、promise和setTimeout的执行顺序

整会promise这8个高级用法,再被问倒来喷我