async/await深入学习

本文探讨了ES2017引入的async/await特性,通过一段代码示例解析了async函数的返回值及Promise的工作原理。在async函数中,await表达式会暂停函数执行,等待Promise解析完成后继续。尽管await后的Promise已经决议,但由于异步过程,相关语句会被放入microtask queue,导致特定的执行顺序。文章解释了为何在预期之外的顺序执行的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先看这么一段代码:

async function async1() {
console.log('a');
await async2();
console.log('b');
}
async function async2(){
console.log('c');
}
async1();
new Promise(function (resolve) {
console.log('d');
resolve();
}).then(function () {
console.log('e')
});

这一段代码的输出结果是什么呢?答案是
a
c
d
e
b

可能和某些人心里想的不太一样哈,那么接下来就让我们深入探究输出为以上顺序的原因:

先介绍一下ES2017(ES8)的新特性: async/await,使用async function 声明的函数返回的是一个Promise对象,当async函数返回值时,Promise的rosolve方法会负责传递这个值;当async函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。

async 函数中可能会有 await 表达式,这会使 async 函数暂停执行,等待表达式中的 Promise 解析完成后继续执行 async 函数并返回解决结果。

注意,await关键字仅仅在async function中有效。如果在async function函数体外使用 await ,你只会得到一个语法错误(SyntaxError)。

现在,让我们来分析这段代码, 我们声明了async1async2这两个async函数,然后执行async1(),首先执行console.log('a'),然后执行async2()中的console.log('c'),执行完成后async2返回的Promise状态变为fulfilled。然后,因为await的存在,async1暂停执行。

这里要注意,await语句之后的其它语句相当于await后表达式返回的Promise对象的then回调函数,所以async1未执行的部分会进入microtask queue。

紧接着执行new Promise(),作为其参数的函数会立刻执行,所以console.log('d')被执行,执行resolve()后这个Promise的状态变成fulfilled,于是其then方法的回调函数进入microtask queue。
照这样说,console.log('b')在队列中更靠前,应该先输出才对,为什么最后输出呢?

其实,即使await关键字后是一个已经决议的Promise对象,此时也会产生一个新的Promise对象,虽然它会立刻resolve为原Promise的值,但该过程是异步过程,所以进入队列的其实是新Promise的产生,然后async1剩下的语句添加到了队列的末尾,所以最后输出。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值