统一处理async/await异常的核心是分层拦截、集中响应:请求层封装标准化错误并自动重试,业务层按需细粒度捕获,界面层统一兜底与分类响应,建立可识别的错误子类体系实现精准处理。

在项目中统一处理 async/await 异常,核心不是到处写 try/catch,而是分层拦截、集中响应——既避免重复代码,又不丢失错误上下文。
封装请求层:拦截并标准化 API 错误
所有网络请求(如 axios、fetch 封装)应在底层统一捕获异常,转换为结构化错误对象,并决定是否提示用户或静默处理:
- 拦截 4xx/5xx 响应,不直接 throw,而是返回 { success: false, error: new ApiError(...) } 或 reject 统一错误实例
- 对网络失败、超时等非业务错误,自动重试(可配次数)或转为特定错误类型(如 NetworkError)
- 返回 Promise 时始终 resolve,让调用方无需强制 try/catch;也可保留 reject 路径,但确保错误类型一致(如都继承自 BaseApiError)
业务逻辑层:按需细粒度捕获,不盲目吞错
async 函数内部只对能自行恢复的场景做局部 try/catch(比如某一步失败不影响主流程),其他一律向上抛出:
- 例如“加载用户信息失败,但仍可展示默认页”,就 catch 后 return fallbackData
- 但“提交订单失败”这类关键操作,不应在 service 层吞掉错误,而应 throw,交由页面或组件层决策(重试?跳转?弹窗?)
- 避免在每个 await 前加独立 try/catch,除非语义明确且处理方式不同
界面层:统一兜底 + 按场景响应
组件或路由级使用高阶封装或组合式逻辑,把错误处理从业务代码中剥离:
- Vue 中可用 composable 如 useAsync({ apiFn, onError: () => showMsg() }),自动管理 loading/error/state
- React 可封装 suspense fallback + error boundary,配合自定义 Hook 统一处理 pending/rejected 状态
- 全局监听 unhandledrejection,记录日志并上报,防止遗漏未 catch 的 Promise rejection
错误分类与传播:让错误“说话”
统一处理的前提是错误可识别、可路由。建议建立轻量错误体系:
- 定义 Error 子类:AuthError、ValidationError、NetworkError、BusinessError 等
- 后端返回的 code/message 需映射到对应类型,便于上层 switch 判断
- throw 时不只 throw new Error('msg'),而是 throw new BusinessError({ code: 'ORDER_PAY_FAIL', detail: ... })
- 这样上层可精准响应:“code === 'TOKEN_EXPIRED' → 跳登录页”,而非模糊提示“出错了”











