You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何async函数返回Promise首次打印为pending,其余为fulfilled?

问题原因解析

这个现象和你加不加await没有关系,核心是async函数的返回值包装规则+JS微任务调度机制,具体拆解:

普通函数返回Promise的状态逻辑

testFunc2和testFunc3是普通箭头函数,返回Promise的逻辑非常直接:

  • Promise构造器传入的executor函数是同步执行的,你写在里面的resolve()会在函数调用的同步阶段立刻触发
  • 所以当你在同步代码行打印这两个函数的返回值时,Promise已经被同步标记为fulfilled状态,自然显示<fulfilled>: undefined

async函数返回Promise的特殊逻辑

被async修饰的testFunc,返回值规则和普通函数有本质区别:

  • 不管async函数内部return的是什么值——哪怕是一个已经resolve的Promise实例——函数被调用时,都会先同步返回一个全新的、处于pending状态的外层Promise
  • 内部return的值会被丢进微任务队列做状态对齐:必须等当前所有同步代码执行完,才会跑这个微任务,把外层Promise的状态改成和内部return的Promise一致
  • 你在同步阶段打印testFunc()的返回值时,状态对齐的微任务还没轮到执行,所以看到的是pending状态。这个Promise不会一直卡pending,只是你打印的时机太早,没等到它状态流转完成。

输出顺序的逻辑

你看到的回调执行顺序,完全是微任务队列先进先出调度的结果:

  • 同步执行阶段,testFunc2和testFunc3返回的Promise已经同步resolve,所以它们的第一个then回调(打印1、打印4)会直接加入微任务队列;而testFunc的外层Promise还在等状态对齐的微任务,它的第一个then回调(打印Hello)要等状态对齐完成才会入队,自然比前两个的第一个回调晚执行
  • 后续链式调用的then回调,都会等上一个回调执行完才会依次入队,最终就得到了你贴出来的输出顺序

验证方式

你只要把打印testFunc()返回值的逻辑放到异步任务里,等过了第一个微任务周期再打,就能看到它最终是fulfilled状态:

// 放到微任务中打印
Promise.resolve().then(() => console.log(testFunc()))
// 放到宏任务中打印
setTimeout(() => console.log(testFunc()), 0)

这两处打印的结果都会是Promise {<fulfilled>: undefined}。

内容的提问来源于stack exchange,提问作者Georgy27OP

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 22:48:36