async 和 await 是基于 Promise 的异步语法糖:async 函数返回 Promise,await 暂停执行直至 Promise 完成;需在 async 函数内使用,配合 try/catch 处理错误,支持自动包装非 Promise 值,但须合理设计串行/并行逻辑。
它们是 JavaScript 中处理异步操作的语法糖,本质仍是基于 Promise,但让异步代码写起来像同步代码一样线性、易读。async 用于声明一个函数会返回 Promise,await 只能在 async 函数内部使用,用来“暂停”执行直到右侧的 Promise 被 resolve 或 reject。
直接在 async 函数里用 await fetch(...) 获取响应,再用 await response.json() 解析数据。注意:两次 await 都可能抛错,必须捕获。
async function getUser() {
try {
const response = await fetch('/api/user');
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const data = await response.json();
return data;
} catch (err) {
console.error('获取用户失败:', err.message);
}
}
fetch() 本身只在网络失败时 reject,HTTP 404/500 不会触发 catch,得手动检查 response.ok
await,否则报错 Uncaught SyntaxError: await is only valid in async function
await Promise.all([...]) 套两层,直接 await Promise.all([fetch(...), fetch(...)])
await 会自动把非 Promise 值包装成已 resolve 的 Promise。比如 await 42 等价于 await Promise.resolve(42),所以能安全地混用同步值和异步逻辑。
await 处理缓存命中(返回普通对象)和缓存未命中(返回 Promise)await 没实际意义,还可能掩盖本该同步执行的逻辑意图await 42 的类型为 number,需显式标注或依赖上下文没加 try/catch,或只捕获了第一层 await,后续链式调用仍可能出错。尤其在连续 await 多个异步操作时,任一环节 reject 都会导致整个函数中断。
async function badExample() {
const user = await fetchUser(); // 如果这里 reject,下面不会执行
const posts = await fetchPosts(user.id); // 这行根本跑不到
return { user, posts };
}
await 行为都可能失败,建议按业务粒度包裹 try/catch,而不是整个函数包一层await:比如 for (const id of ids) await fetch(`/item/${id}`) 是串行,性能差;改用 Promise.all(ids.map(id => fetch(...)))
async 函数返回值总是 Promise,即使你 return 123,调用方也必须用 .then() 或外层 await 接收