async函数返回值必为Promise对象:原始值自动包装为Promise.resolve(),错误转为Promise.reject(),已存在的Promise不二次包装,这是为保障await行为统一及微任务调度所必需。

async 函数的返回值类型只有一个:Promise 对象。不管你 return 什么,甚至不写 return,它都返回 Promise —— 这不是“大概率”或“通常情况”,而是 JavaScript 引擎强制执行的语言规范。
所有返回值都会被自动包装
async 函数内部 return 的原始值(数字、字符串、对象、undefined)会被隐式传入 Promise.resolve();抛出错误则等价于 Promise.reject()。你不需要、也不应该手动调用 Promise.resolve()。
-
return 100 → 返回
Promise.resolve(100) -
return "done" → 返回
Promise.resolve("done") -
没有 return 语句 → 等价于
return undefined,即Promise.resolve(undefined) -
throw new Error("fail") → 返回
Promise.reject(new Error("fail"))
直接返回 Promise 不会二次包装
如果 async 函数里 return 的已经是 Promise(比如调用了 fetch 或另一个 async 函数但没 await),JavaScript 不会再套一层 Promise,而是直接返回那个 Promise 实例。
-
return fetch("/api") → 返回该 fetch 返回的 Promise,不是
Promise.resolve(fetch(...)) - return someAsyncFn()(未 await)→ 返回那个函数返回的 pending Promise
- 这种写法容易导致“嵌套 Promise”问题,例如返回
Promise<Promise<number>>,应尽量避免
为什么必须是 Promise?
await 表达式只能等待 thenable 对象,而 Promise 是最标准的实现。如果 async 函数有时返回字符串、有时返回 Promise,await fn() 的行为就无法统一:你可能拿到值,也可能拿到 Promise,整个异步流程会失去可预测性。
立即学习“Java免费学习笔记(深入)”;
- Promise 提供了统一的消费方式:
.then()、.catch()、Promise.all()、await - async 函数体实际被编译为状态机,依赖 Promise 的 pending/fulfilled/rejected 状态来驱动暂停与恢复
- 它的执行被安排在微任务队列中,这天然绑定 Promise 的调度机制
怎么拿到真正的返回值?
你不能绕过 Promise 直接拿到原始值,必须通过异步方式提取:
- 在另一个 async 函数中:const val = await myAsyncFn()
- 在非 async 环境中:myAsyncFn().then(val => console.log(val))
- 错误要通过
.catch()或 try/catch(在 await 外层)捕获


















