遇到这么一个面试题
async function async1() {
return Promise.resolve(1);
}
async1().then((res) => {
console.log(res);
})
new Promise((resolve) => {
resolve('2');
}).then((res) => {
console.log(res);
}).then(() => {
console.log(3);
})
要求说出代码执行结果,很多人说1,2,3;但其实是2,3,1
核心机制:async 函数返回 Promise 的包装行为
当 async 函数返回一个 Promise 时,引擎会执行以下步骤:
- 隐式包装
async函数始终返回一个新的 Promise(记作p)。
如果函数内部返回一个非 Promise 值(如return 1),p会直接以该值解决,无需额外步骤。 - 返回 Promise 时的特殊处理
如果函数内部返回一个 Promise(如return Promise.resolve(1)),引擎会:
-
- 解包(Unwrap):等待这个内部 Promise 解决。
- 同步状态:将
p(外层 Promise)的状态与内部 Promise 同步。 - 触发微任务:此过程需要 至少一个额外的微任务 来完成同步。
具体代码分析
以下面的代码为例:
async function async1() {
return Promise.resolve(1); // 返回一个 Promise
}
执行步骤详解:
- 调用
async1()
-
- 引擎创建一个新的 Promise
p1(由async隐式生成)。 - 执行函数体,遇到
return Promise.resolve(1),记内部 Promise 为p2。
- 引擎创建一个新的 Promise
- 解析
p2到p1
-
- 引擎需要将
p1的状态与p2同步。 - 通过调用
p2.then(实现同步。
(value) => resolve(p1, value),
(error) => reject(p1, error)
) - 这一步会生成一个微任务(等待
p2完成)。
- 引擎需要将
- 微任务队列的变化
-
- 当
p2是已解决的 Promise(如Promise.resolve(1)),其.then()回调(同步p1状态)会被放入微任务队列。 - 此时,
async1().then(...)的回调(即console.log(res))需等待p1解决,而p1的解决又依赖上述微任务。
- 当
得出代码执行顺序
- 初始微任务队列:
-
[处理 new Promise 的 .then(res => console.log(2))]
- 第一轮微任务处理:
[
() => console.log(3),
() => console.log(1)
]
-
- 执行
console.log(2)→ 输出 2。 - 链式调用
.then(() => console.log(3))的回调进入队列。 - 同时,
async1()的第一个微任务(解析内部 Promise)完成,其外层 Promise 的.then()回调(console.log(1))进入队列。
此时队列变为:
- 执行
- 第二轮微任务处理:
-
- 执行
console.log(3)→ 输出 3。 - 执行
console.log(1)→ 输出 1。
- 执行
深入解析async返回结果的执行顺序
4123

被折叠的 条评论
为什么被折叠?



