为 async 函数写容错逻辑的核心是明确错误来源、分类响应、控制重试边界并确保状态可恢复:需区分网络层错误(重试+降级)、客户端校验失败(提前拦截)、服务端业务错误(解析响应走业务分支),监听 unhandledrejection;坚持单点 await + 显式 try/catch,避免 .catch 链式污染;合理使用 Promise.allSettled()、幂等重试与退避策略;在 finally 中统一清理副作用,检查组件挂载状态,禁止静默吞错。

为 async 函数写容错逻辑,核心不是“捕获所有错误”,而是明确错误来源、分类响应、控制重试边界,并确保状态可恢复。
区分错误类型,针对性处理
async 函数抛出的错误可能来自网络请求、数据解析、业务校验或并发竞争。统一 try/catch 会掩盖问题本质。
- 网络层错误(如 fetch 超时、5xx)适合重试 + 降级(返回缓存或默认值)
- 客户端校验失败(如参数不合法)属于编程错误,应提前拦截,不进 async 流程
- 服务端业务错误(如 403、404、自定义 error code)需解析响应体,走业务分支而非当异常处理
- 未 caught 的 Promise rejection 会触发 unhandledrejection,务必监听并记录(开发期报警,线上收敛)
用 await + try/catch 控制执行流,避免 .catch 链式污染
混用 then().catch() 和 await 容易丢失上下文、难以调试。坚持单点 await + 显式 try/catch 更可控。
- 每个 await 后都考虑是否需要单独捕获:比如先 fetch 再 parse,fetch 失败和 JSON.parse 失败应分开处理
- 避免在 async 函数里 return promise.then().catch() —— 这会让函数实际返回 Promise<void>,丢失原始返回类型
- 若需并行请求且部分失败可接受,用 Promise.allSettled() 替代 Promise.all()
加入合理重试与退避机制
盲目重试会放大雪崩风险。重试必须带条件、次数上限和退避策略。
- 只对幂等操作(GET、PUT)重试;POST/DELETE 重试前需确认服务端是否支持幂等(如带 idempotency key)
- 限制重试次数(通常 2~3 次),首次延迟 100ms,后续指数退避(如 100ms → 300ms → 900ms)
- 重试时记录尝试次数和错误原因,便于排查是瞬时故障还是持续异常
- 可封装通用 retry 工具函数,接收 async fn、最大次数、判断是否可重试的 predicate
保证状态一致性与资源清理
async 操作常伴随副作用:打开 loading、修改 store、启动定时器、订阅事件。出错时这些状态必须归位。
- 在 try 块外初始化副作用(如 setIsLoading(true)),在 finally 中统一收尾(setIsLoading(false))
- 若涉及可取消操作(如 AbortController),在 catch 或 finally 中调用 abort() 防止内存泄漏
- 更新 UI 或状态前,检查组件是否 still mounted(React 中用 useRef 记录 mounted 状态)
- 避免在 catch 中静默吞掉错误 —— 至少 log 错误,必要时上报监控系统


















