async/await需手动捕获异常,可通过wrapasync高阶函数封装实现统一错误包装与结构化返回;支持自定义错误类、类型守卫及operational错误区分,兼顾业务异常处理与开发体验。

在 JavaScript 中,async/await 本身不提供自动异常捕获机制,但可以通过封装 Promise 处理逻辑,实现对异步操作中抛出的错误进行统一包装(例如统一添加错误码、上下文信息、日志标记等),避免每个 await 后都写 try/catch。
用高阶函数封装 async 操作
核心思路是将 async 函数包裹进一个返回 Promise 的工厂函数,在内部统一处理 reject 和 throw 的情况。
- 定义一个 wrapAsync 工具函数,接收原始 async 函数和可选的错误包装配置
- 在内部调用时用 try/catch 捕获异常,并构造标准化错误对象(如 { code: 'ERR_FETCH', message, timestamp, originalError })
- 成功时返回 { data, error: null },失败时返回 { data: null, error: wrappedError } —— 这种“结果对象”模式便于调用方统一判空
配合自定义错误类增强类型与语义
为不同业务场景定义继承自 Error 的子类(如 ApiError、NetworkError、AuthError),并在 wrapAsync 中根据原错误类型或响应状态码做映射。
- 例如 fetch 失败时,若 response.status === 401,抛出 new AuthError('Token expired')
- 统一包装函数识别该实例,补充 traceId、请求路径等字段,再 re-throw 或返回结构化错误
- TypeScript 中可配合类型守卫缩小 error 类型,提升后续处理的安全性
在业务层使用时保持简洁
封装后,业务代码无需分散 try/catch,只需解构标准响应对象即可。
- const { data, error } = await wrapAsync(fetchUser)(userId)
- if (error) { handleCommonError(error); return; }
- use data normally —— 逻辑更线性,错误路径集中可控
- 也可结合 React Query、RTK Query 等库的 queryFn 层做统一拦截,进一步下沉包装逻辑
注意边界:不要掩盖编程错误
统一包装适用于预期中的业务/网络异常(如 4xx/5xx、超时、连接中断),但不应吞掉 ReferenceError、TypeError 等开发阶段错误。
- 可在包装函数中判断 error instanceof Error && !error.isOperational(约定字段)来区分
- 非 operational 错误直接 throw,触发全局未捕获异常处理器(如 window.onerror)用于监控告警
- 避免“静默失败”,确保开发体验不降级
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











