在 async 函数中捕获异常的关键是精准定位 try/catch 位置:必须包裹每个可能失败的 await 表达式(如 fetch、res.json()),而非仅外层包裹;多个独立请求应使用 promise.allsettled() 或单独 .catch(),避免 promise.all() 过度中断;顶层调用需 .catch(),并配合 unhandledrejection 全局兜底;高频场景应封装 to() 工具或健壮 fetch 包装器。

在 async 函数里捕获异常,关键不是“加不加 try/catch”,而是**在哪加、加给谁、后续怎么响应**。async/await 本质是 Promise 语法糖,错误走的是 Promise reject 流,不是同步 throw,所以位置错一点,错误就漏掉了。
必须在 await 表达式内部用 try/catch
fetch、axios、res.json() 这些操作的错误不会在调用时立即抛出,而是在 await 后续解析或校验阶段才触发 reject。外部包裹无效,必须把具体 await 语句包进 try 块:
- ✅ 正确:对 每个可能失败的 await 步骤 做检查,比如判断
res.ok、调用res.json() - ❌ 错误:只在函数最外层 try 一下,却让
await fetch().then(...)或return fetch().catch()混在里面——这会绕过 catch - ⚠️ 注意:catch 里别只打日志,要明确返回值(如
return null)或重新 throw,否则调用方无法感知失败
多个独立请求,别共用一个 try/catch
如果同时拉用户信息、通知列表、配置项,一个挂了不该让其他也失效:
- 推荐用
Promise.allSettled():它不中断,返回每个任务的{ status: 'fulfilled' | 'rejected', value | reason },逻辑清晰可控 - 也可为每个请求单独链
.catch(() => defaultValue),再await Promise.all([p1, p2, p3]) - 慎用
Promise.all():只要一个 reject,整个数组就失败,除非你真需要“全成功才继续”
顶层和全局兜底不能少
局部处理再细,也容易漏掉没 await 的调用、没 catch 的 Promise 返回值,或者第三方库抛的异常:
- 所有顶层 async 调用(比如按钮点击、页面加载)都要配
.catch(),例如loadData().catch(handleError) - 浏览器加
window.addEventListener('unhandledrejection', ...),捕获所有未被处理的 Promise reject - 配合
window.onerror捕获同步错误和资源加载失败,构成基础防线
高频场景可封装工具函数
如果项目里反复出现 await api().catch(() => null) 或 await api().catch(err => { log(err); return default }),说明该抽象了:
- 写个
to(promise)工具:返回[error, result]数组,类似 Go 风格,调用方用解构判断 - 或封装带默认值、自动上报、带重试的 fetch 包装器,把重复逻辑收口
- 避免每个地方都手写 try/catch,降低出错概率,也方便统一升级策略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











