async/await 是 Promise 的语法封装而非新语法糖,它通过自动包装返回值为 Promise、暂停执行而不阻塞主线程、强制 try/catch 错误处理及需配合 Promise.all 实现并发等机制,简化异步流程但不改变事件循环本质。
async/await 不是新语法糖,而是 Promise 的语法封装;它不能替代 Promise,但能显著降低回调嵌套和错误处理的复杂度。
声明一个 async 函数,等价于手动包装一个返回 Promise 的函数。调用它总会得到一个 Promise 实例,哪怕你 return 42,它也会被自动包装成 Promise.resolve(42)。
常见误解:以为 async 让函数“变同步”了——其实它只是让 await 可以暂停函数执行(仅限当前函数体),底层仍是事件循环驱动。
async 函数内部遇到 await 会暂停,把控制权交还给事件循环,不阻塞主线程await 后面不是 Promise,会自动用 Promise.resolve() 包装Promise.reject(err)
直接在顶层或普通函数里写 await 会报 SyntaxError: await is only valid in async functions。这是语法限制,不是运行时错误。
常见场景应对方式:
(async () => { ... })() 立即执行async function handleClick() { ... }
Promise.all([p1,
p2, p3])
async function fetchUsers() {
try {
const res = await fetch('/api/users');
const users = await res.json();
return users;
} catch (err) {
console.error('Fetch failed:', err);
throw err;
}
}
await 后的 Promise 被 reject,会直接抛出异常,不会像 .then().catch() 那样隐式传递。漏写 try/catch 就会导致未捕获异常(Uncaught (in promise))。
特别注意:
await Promise.reject('oops') 会立即触发 catch 块,不是“跳过后续代码”而是中断当前 async 函数执行流await 连续写时,任一失败都会终止后续 await,除非你对每个都单独 try/catchawait something().catch(() => {}) 或用空数组兜底写 for (const url of urls) { await fetch(url); } 是串行请求,总耗时 ≈ 所有请求时间之和。真正并发要先发所有请求,再统一 await。
正确做法:
const promises = urls.map(u => fetch(u))
const responses = await Promise.all(promises)
Promise.allSettled() 替代 Promise.all()
async function fetchAll(urls) {
const promises = urls.map(url =>
fetch(url).then(r => r.json()).catch(() => null)
);
return await Promise.all(promises);
}
最易被忽略的一点:await 不会“等整个异步链”,它只等紧跟着的那个 Promise 完成。如果你忘了链式调用中某处没 return,后续 await 就可能等错对象——比如漏了 return 导致 await 等到 undefined,再被包装成已 resolve 的 Promise,逻辑就悄悄跑偏了。