async/await 错误处理需区分网络错误(4xx/5xx)和业务错误(http 200但code非0),前者通过检查res.ok或status主动throw,后者解析json后按code手动throw;统一继承自error并携带code/raw字段,便于分类处理;避免promise.reject未await、连续await中断执行及未监听unhandledrejection。

async/await 模式下处理非标准异步错误,关键在于区分两类错误:网络/HTTP 层错误(如 404、断网)和业务层错误(如 HTTP 200 但 code: 4001)。前者会被 try/catch 自动捕获,后者不会——因为响应成功抵达,只是后端用约定字段表达了失败。
先拦截真实 HTTP 错误
用封装函数统一检查响应状态,把 4xx/5xx 主动转为异常:
- 调用
fetch后立即判断res.ok或res.status - 不满足则
throw new Error(`HTTP ${res.status}`),这样会进catch - 这一步能捕获超时、服务不可用、路径错误等真实请求失败
再校验业务响应体
HTTP 成功后,必须手动解析 JSON 并检查业务字段(如 code、success、error):
- 假设后端返回结构为
{ code: number, data: any, msg: string } - 若
body.code !== 0(或!body.success),构造带语义的错误对象 - 推荐写法:
const err = new Error(body.msg); err.code = body.code; err.raw = body; throw err;
统一错误类型便于后续处理
让所有错误(网络错 + 业务错)都继承自同一逻辑,避免分支判断混乱:
- 在
catch中可通过err.code区分是登录过期(401)、参数错误(4000)还是用户名已存在(4001) - 保留
err.raw可用于日志上报、重试逻辑或前端特殊提示 - 不建议只用
alert(err.message),应结合错误码做差异化响应
避免常见陷阱
几个容易忽略但影响稳定性的点:
-
return Promise.reject(...)不会被try/catch捕获,必须写成return await Promise.reject(...) - 多个
await连续调用时,一个失败会中断后续执行;需按需拆分try/catch块或使用to()封装 - 未监听
unhandledrejection会导致静默失败,建议全局兜底











