能力:请求重试(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_CANCELED、AbortError、ABORT_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';
}
}
}
});配置项
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled | boolean | true | 能力开关 |
attempts | number | 3 | 最大执行次数(1=不重试,2=重试 1 次,3=重试 2 次) |
delay | number | 300 | 初始延迟时间(ms) |
backoff | string | 'exponential' | 退避算法:fixed / linear / exponential |
methods | string[] | [] | 允许重试的方法白名单(空=不限制) |
excludeMethods | string[] | ['POST','PUT','PATCH','DELETE'] | 排除重试的方法(请求级不受限制) |
statusCodes | number[] | [408,429,500,502,503,504] | 允许重试的 HTTP 状态码 |
errorCodes | string[] | ['ECONNABORTED','ETIMEDOUT'] | 允许重试的网络错误码 |
canRetry | function | null | null | 自定义判断函数,优先级最高 |
自定义重试判断(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 字段
| 字段 | 类型 | 说明 |
|---|---|---|
config | object | 当前正在处理的请求配置 |
options | object | 当前生效的 retry 配置 |
error | any | 当前这次尝试捕获到的错误 |
attempt | number | 当前失败的是第几次尝试(1-based) |
retryIndex | number | 当前即将进入的是第几次重试(1-based) |
nextAttempt | number | 下一次尝试的序号(1-based) |
status | number | undefined | 从错误对象中提取到的 HTTP 状态码 |
code | string | undefined | 从错误对象中提取到的错误码 |
methods 白名单 vs excludeMethods
methods 是允许重试的方法白名单,excludeMethods 是排除列表,两者互为补充:
methods: [](默认)表示不额外限制,由excludeMethods决定排除项- 同时配置时,请求方法需同时在
methods白名单内、且不在excludeMethods中才会重试 - 请求级显式 retry 配置不受
excludeMethods限制,但受methods限制(如果显式配置了methods)
退避算法
| 算法 | 公式 | 示例(delay=200) |
|---|---|---|
fixed | delay | 200, 200, 200 |
linear | delay × attemptIndex | 200, 400, 600 |
exponential | delay × 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 逻辑 |

