Skip to content

能力:请求重试(Retry)

网络抖动、服务端瞬断时,自动重试失败请求,业务代码无需任何感知。

什么时候该用 / 别用

场景该不该用原因
GET 查询、配置拉取✅ 该用幂等读操作,重试无副作用
上游服务偶发 502/503✅ 该用瞬断重试通常能恢复
POST 创建订单、支付⚠️ 默认不重试非幂等写操作,重试可能重复创建。除非接口保证幂等(带幂等 key)
用户主动取消的请求❌ 不重试ERR_CANCELED / AbortError 默认就不重试
400/401/403 业务错误❌ 不重试不在可重试状态码白名单,重试也是同样的错

写操作想重试怎么办?

retry 默认排除 POST/PUT/PATCH/DELETE。如果你的 POST 接口保证幂等(如带 Idempotency-Key),可在请求级显式开启——请求级配置不受 excludeMethods 限制。

默认行为

  • 默认 attempts: 3(首次 + 2 次重试),retry: true 开箱即重试
  • 默认 delay: 300 + backoff: 'exponential'(指数退避:300ms → 600ms → ...),避免瞬时重试加重故障服务压力
  • 默认排除 POST / PUT / PATCH / DELETE(写操作不自动重试)
  • 只重试白名单内的 HTTP 状态码:408, 429, 500, 502, 503, 504
  • 只重试白名单内的网络错误码:ECONNABORTED, ETIMEDOUT
  • 304、ERR_CANCELEDAbortErrorABORT_ERR 和 Axios legacy cancel 绝不重试

单业务场景配置

javascript
// ============ 全局开启:GET 请求自动重试 ============
const requestManager = setupRequestGuard(axios, {
  defaults: {
    retry: {
      attempts: 3,            // 最多尝试 3 次(首次 + 2 次重试)
      delay: 200,             // 初始延迟 200ms
      backoff: 'exponential'  // 指数退避:200ms → 400ms → 800ms
    }
  }
});

// ============ 请求级覆盖:某个接口重试 5 次 ============
await axios.get('/api/config', {
  requestGuard: {
    retry: {
      attempts: 5,            // 这个接口比较重要,多试几次
      delay: 500,
      backoff: 'linear'       // 线性退避:500ms → 1000ms → 1500ms → 2000ms
    }
  }
});

// ============ POST 请求显式开启重试 ============
// 默认排除写操作,但请求级配置不受此限制
await axios.post('/api/idempotent-action', data, {
  requestGuard: {
    retry: {
      attempts: 2,           // 重试 1 次
      delay: 1000            // 等 1 秒再试
    }
  }
});

// ============ 自定义重试判断 ============
await axios.get('/api/data', {
  requestGuard: {
    retry: {
      attempts: 3,
      delay: 300,
      // canRetry 优先级最高,配置后不再走内部白名单逻辑
      canRetry({ error, attempt, status, code }) {
        return status === 503 || code === 'ECONNABORTED';
      }
    }
  }
});

配置项

配置项类型默认值说明
enabledbooleantrue能力开关
attemptsnumber3最大执行次数(1=不重试,2=重试 1 次,3=重试 2 次)
delaynumber300初始延迟时间(ms)
backoffstring'exponential'退避算法:fixed / linear / exponential
methodsstring[][]允许重试的方法白名单(空=不限制)
excludeMethodsstring[]['POST','PUT','PATCH','DELETE']排除重试的方法(请求级不受限制)
statusCodesnumber[][408,429,500,502,503,504]允许重试的 HTTP 状态码
errorCodesstring[]['ECONNABORTED','ETIMEDOUT']允许重试的网络错误码
canRetryfunction | nullnull自定义判断函数,优先级最高

自定义重试判断(canRetry)

canRetry 优先级最高,配置后不再走内部白名单逻辑。它接收一个 RetryDecisionContext,返回 true 继续重试、false 停止:

javascript
await axios.get('/api/data', {
  requestGuard: {
    retry: {
      attempts: 3,
      delay: 300,
      canRetry(context) {
        return context.status === 503 || context.code === 'ECONNABORTED';
      }
    }
  }
});

canRetry context 字段

字段类型说明
configobject当前正在处理的请求配置
optionsobject当前生效的 retry 配置
errorany当前这次尝试捕获到的错误
attemptnumber当前失败的是第几次尝试(1-based)
retryIndexnumber当前即将进入的是第几次重试(1-based)
nextAttemptnumber下一次尝试的序号(1-based)
statusnumber | undefined从错误对象中提取到的 HTTP 状态码
codestring | undefined从错误对象中提取到的错误码

methods 白名单 vs excludeMethods

methods 是允许重试的方法白名单,excludeMethods 是排除列表,两者互为补充:

  • methods: [](默认)表示不额外限制,由 excludeMethods 决定排除项
  • 同时配置时,请求方法需同时在 methods 白名单内、且不在 excludeMethods 中才会重试
  • 请求级显式 retry 配置不受 excludeMethods 限制,但受 methods 限制(如果显式配置了 methods

退避算法

算法公式示例(delay=200)
fixeddelay200, 200, 200
lineardelay × attemptIndex200, 400, 600
exponentialdelay × 2^(attemptIndex-1)200, 400, 800

429 + Retry-After

当服务端返回 429 状态码时,自动解析 Retry-After header 并覆盖配置的延迟时间:

javascript
// 服务端返回:429 Too Many Requests + Retry-After: 5
// guard 自动等待 5 秒后重试,无需业务处理

状态清理

场景行为
clearState()waiting 状态立即取消(抛 RequestGuardRetryCancelledError);inFlight 让其自然完成但不再继续重试
uninstall()同 clearState 语义,额外解绑定时器和事件监听
requestGuard: false完全绕过守护层,不进入 retry 逻辑

基于 MIT 许可发布