async/await 错误处理需确保 await 在 try 内、按业务拆分 try-catch、细粒度判断错误类型,并在调用层兜底。否则错误会被忽略或全局抛出。

在 JavaScript 异步函数(async/await)中,try-catch 是最直接、最可控的错误处理方式,但必须注意 await 的位置和 Promise 拒绝的时机,否则错误会 silently 被吞掉或抛到全局。
await 必须在 try 块内才能被捕获
只有被 await 的 Promise 被拒绝(reject),且该 await 位于 try 块中,错误才会进入 catch。如果漏写 await,得到的是一个未执行的 Promise 对象,不会触发 reject,也就不会进 catch。
✅ 正确写法:
async function fetchData() {
try {
const res = await fetch('/api/data'); // await 在 try 内
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json();
} catch (err) {
console.error('请求失败:', err.message);
throw err; // 可选择重新抛出
}
}
避免在 catch 中忽略关键错误类型
不是所有异常都该一视同仁。网络中断、401 认证失败、404 资源不存在、500 服务端错误,处理策略应不同。建议用 instanceof 或检查 err.name/err.status 做细粒度判断。
- 对
TypeError(如网络断开、fetch 失败)可重试或提示“请检查网络” - 对 HTTP 状态码 401,应跳转登录页或刷新 token
- 对 404,可显示友好提示而非报错弹窗
- 对未预期错误(如
ReferenceError),应记录日志并 fallback
多个 await 不要共用一个 try-catch(除非逻辑强相关)
把不相关的异步操作塞进同一个 try 块,会导致前一个失败后,后续操作完全跳过,掩盖真实问题。更合理的方式是按业务单元拆分,或为每个关键 await 单独兜底。
❌ 不推荐:
try {
const user = await getUser();
const posts = await getPosts(user.id); // 若 getUser 成功但 getPosts 失败,user 已加载却无法复用
const profile = await getProfile(user.id);
} catch (err) { ... }
✅ 更健壮的做法:
const user = await getUser().catch(err => {
console.warn('获取用户失败,使用默认信息', err);
return DEFAULT_USER;
});
const posts = await getPosts(user.id).catch(() => []);
const profile = await getProfile(user.id).catch(() => ({}));
不要忘记 async 函数本身也是 Promise
调用方仍需处理这个 Promise 的拒绝 —— 不能只依赖内部 try-catch。尤其在事件回调、生命周期钩子等场景,未捕获的 Promise rejection 会触发 unhandledrejection,影响稳定性。
✅ 推荐调用方式:
- 在顶层用
.catch():fetchData().catch(handleAsyncError) - 在事件中用
async匿名函数 +try-catch:button.addEventListener('click', async () => { try { await fetchData(); } catch (e) { showNotice(e); } }); - 开发阶段监听全局未处理 rejection:
window.addEventListener('unhandledrejection', e => console.error('未捕获 Promise 错误:', e.reason));
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











