async函数本质是返回Promise的函数,无论是否含await,调用必返回Promise对象;返回值自动包装为Promise.resolve(),抛错等价于Promise.reject()。

async 函数本质就是返回 Promise 的函数
声明为 async 的函数,无论函数体里写没写 await,调用它**一定返回一个 Promise 对象**。这是语言层面的硬性规则,不是约定俗成。
如果函数正常返回一个值(比如 return 42),这个值会被自动包装进 Promise.resolve(42);如果抛出错误(throw new Error()),则等价于 Promise.reject(...)。
async function foo() {
return 'hello';
}
console.log(foo()); // Promise { 'hello' }
async function bar() {
throw new Error('oops');
}
console.log(bar()); // Promise { Error: oops }
不写 await,async 函数也照样返回 Promise
很多人误以为 await 是 async 函数“变异步”的原因——其实不是。await 只是暂停当前函数执行、等待 Promise settle,而 async 关键字本身只负责两件事:确保返回 Promise、提供 await 语法支持。
- 没写
await的async函数,行为和Promise.resolve(...)几乎一致 - 写了
await后,函数内部执行顺序变成异步链式,但对外接口仍是 Promise - 想绕过 Promise?做不到。即使
return Promise.resolve(123),结果还是嵌套的Promise { Promise { 123 } }(因为外层已自动包装)
常见错误:把 async 函数当同步函数用
最典型的坑是忘记 await 或 .then(),直接拿返回值当普通数据用:
立即学习“Java免费学习笔记(深入)”;
async function fetchData() {
return { id: 1, name: 'Alice' };
}
const user = fetchData(); // ❌ user 是 Promise,不是对象
console.log(user.name); // undefined
正确做法只有两种:
- 在另一个
async函数里用await fetchData() - 用
fetchData().then(user => {...})
试图用 JSON.stringify(fetchData()) 或 Array.from(fetchData()) 也会失败——它们不接受 Promise。
async 函数里 return Promise 和 return 普通值的区别
看起来没区别,但底层 Promise 状态链不同:
-
return Promise.resolve(42)→ 返回的 Promise 状态由该内部 Promise 决定,但外层仍会再包一层(所以是 resolved Promise 中的 resolved Promise) -
return 42→ 等价于return Promise.resolve(42),但更干净,推荐 -
return Promise.reject('err')→ 外层 Promise 状态仍是 rejected,但堆栈可能被截断,调试更难
除非你要显式控制 resolve/reject 时机(比如配合 setTimeout 手动构造 Promise),否则直接 return 值或 throw 错误最安全。
真正容易被忽略的是:async 函数的执行上下文切换开销虽小,但在高频循环或性能敏感路径中,无意义地加 async 会多一次微任务排队。别为了“看起来现代”而滥用它。











