优雅重试需识别错误类型:临时性错误(如超时、503)可重试,确定性错误(如401、404、库存不足)应终止并降级;用async-retry控制节奏与退出,配合promise.allsettled实现并行任务隔离,再通过统一执行壳收敛重试逻辑。

优雅重试 async 任务,关键不是反复调用,而是有判断、有节制、有退路——它得知道什么时候该停,什么时候该换方案,而不是盲目轮转。
主动识别错误类型,决定是否值得重试
不是所有失败都适合重试。网络超时、503 服务不可用、连接被拒绝这类临时性错误,可以尝试重试;而 401(未登录)、403(权限不足)、404(资源不存在)、业务 code=-1(库存不足)等确定性错误,重试毫无意义,应直接终止并走降级逻辑。
- fetch 后必须检查 response.status,对 4xx/5xx 主动 throw 或返回特定错误
- 解析响应体后,检查 data.code !== 0 等业务字段,非成功态要明确抛出语义化错误(如
new BusinessError(data.code, data.msg)) - 避免把所有 reject 都丢给 retry 库——它无法理解“登录过期”和“网关超时”的区别
用 async-retry 控制重试节奏与退出条件
async-retry 提供了 bail() 函数,让你在特定错误下立刻跳出重试循环,避免无效兜底。
- 在 retry 回调中接收 bail 参数,遇到认证失败、参数错误等确定性错误时,调用
bail(new Error('Unauthorized')) - 配置 retries: 3、minTimeout: 200、factor: 2 实现指数退避,防止请求雪崩
- 不设无限重试,也不用固定间隔——退避策略让系统更健壮
并行任务失败时,单点隔离不中断整体
多个 async 任务同时执行时,一个失败不该拖垮全部。Promise.allSettled 是更稳妥的选择。
- 用 Promise.allSettled([taskA(), taskB(), taskC()]) 替代 Promise.all,每个子任务可独立重试 + fallback
- 结果数组中每个元素含
{ status: 'fulfilled' | 'rejected', value | reason },便于按需处理 - 核心数据失败则报错,辅助模块(如推荐位、头像加载)失败可返回空数组或缓存值,保持主流程可用
封装统一执行壳,收敛重试逻辑
避免每个函数都手写 try/catch + bail + fallback。封装一个高阶函数,把重试、校验、降级、上报一并收口。
- 输入:业务函数、重试配置、fallback 默认值、错误码映射表(如
{ 401: 'auth', 503: 'retry' }) - 内部自动做 status/code 校验,匹配规则后走对应分支:重试 / 降级 / 报错 / 忽略
- 记录结构化日志(traceId、错误码、重试次数),方便定位是网络抖动还是服务异常
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











