async/await 是 Promise 的语法封装,不能替代 Promise;async 函数自动返回 Promise,await 只能在 async 函数内使用,会暂停当前函数但不阻塞主线程,错误需用 try/catch 捕获。

async/await 不是新语法糖,而是 Promise 的语法封装;它不能替代 Promise,但能让异步流程像同步代码一样可读、可调试。
async 函数必须返回 Promise
声明一个 async 函数时,JavaScript 引擎会自动把它包装成返回 Promise 的函数——哪怕你 return 42,实际返回的是 Promise.resolve(42)。
- 如果函数内抛出错误(
throw new Error()),等价于返回Promise.reject() - 不能用
return await somePromise()包裹顶层调用,这多一层不必要的等待;直接return somePromise()更高效 -
async函数内部仍需用try/catch捕获await的异常,而不是靠外层.catch()
async function fetchUser() {
try {
const res = await fetch('/api/user');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('Failed to fetch user:', err.message);
throw err; // 保持 reject 链路清晰
}
}
await 只能在 async 函数内使用
这是常见报错源头:await is only valid in async functions。它不是独立语句,而是 async 函数的专属操作符。
- 不能在普通函数、事件回调(如
addEventListener)、模块顶层直接写await - 想在模块顶层用?ES2022 起支持
top-level await,但仅限 ES 模块(type="module"),且会影响模块初始化顺序 - Node.js 中需加
--experimental-top-level-await(v14.8+ 默认启用),但生产环境慎用,尤其涉及依赖顺序时
await 会阻塞当前 async 函数,但不阻塞主线程
很多人误以为 await 会让整个 JS 线程卡住。其实它只是暂停当前 async 函数的执行,把控制权交还给事件循环,其他任务(如点击事件、定时器)照常运行。
立即学习“Java免费学习笔记(深入)”;
- 连续
await是串行的:多个请求依次发起,总耗时 ≈ 各请求耗时之和 - 想并发?用
Promise.all([p1, p2, p3])包裹后await,总耗时 ≈ 最慢那个请求 -
await Promise.allSettled([...])更稳妥,即使某个请求失败也不中断其余请求
async function loadAll() {
// ❌ 串行:3 秒 + 2 秒 + 1 秒 = ~6 秒
const a = await fetch('/a');
const b = await fetch('/b');
const c = await fetch('/c');
// ✅ 并发:~3 秒(最长那个)
const [a, b, c] = await Promise.all([
fetch('/a'),
fetch('/b'),
fetch('/c')
]);
}
错误处理容易漏掉 try/catch 或忽略 rejected promise
最常被忽视的点:没包 try/catch,又没接 .catch(),导致未捕获异常(unhandledrejection)。
-
await后面的 Promise 被 reject,若没try/catch,会触发全局unhandledrejection事件 - 在 Node.js 中这会导致进程退出(除非监听了
process.on('unhandledRejection')) - 浏览器中虽不崩溃,但控制台报错,且后续逻辑中断
- 不要写
await someAsyncFn().catch(...)—— 这样await等到的是undefined或catch返回值,语义混乱
真正该做的是:始终用 try/catch 包住每个需要容错的 await 表达式,或明确用 .catch() 处理并返回默认值。











