排错指南
常见误区与诊断方法。
🛡️ 防重没生效
症状:请求没有被去重
常见原因:
- 规则没匹配到该请求 — 确认
rules里的method/url真的命中了目标请求(注意 URL 正则是否包含 query) - 能力未安装 — 用 core 按需入口时,确认
capabilities: [duplicate()]已传入;全量入口默认已装 - 请求级配置关掉了 — 确认该请求的
requestGuard.duplicate不是false - 方法被
excludeMethods排除 — duplicate 默认排除GET/OPTIONS/HEAD(读操作该重试/复用,不该阻断)。如果你期望 GET 也去重,需覆盖excludeMethods或在请求级显式开启
GET 默认不去重是预期行为
duplicate 默认 excludeMethods: ['GET','OPTIONS','HEAD'],因为读操作通常该用 reuse 复用或 retry 重试,而不是 block 阻断。要给 GET 开防重,在规则或 defaults 里把 excludeMethods 改成 [],或在请求级显式 requestGuard: { duplicate: true }(请求级不受 excludeMethods 限制)。
// 诊断:开启 debug 级日志观察
setupRequestGuard(axios, {
logger: new ConsoleRequestGuardLogger({ devOnly: true, level: 'debug' })
});症状:两个看起来不同的请求被误判为重复
原因:默认 compareFields 只比较 method/baseURL/url/params/data,如果你在 header 里传了租户 ID、时间戳等区分性字段,它们不参与判重。
解决:用 headerFields / compareHeaders 让指定 header 参与判重,或用 keyGenerator 完全自定义。
duplicate: {
headerFields: ['X-Tenant-Id', 'X-Request-Id']
}症状:FormData 上传总是被判为重复
原因:FormData 无法稳定序列化,默认占位符会把不同表单请求都视为相同。
解决:用 formDataResolver 自定义判重值。见 常见业务场景 - 文件上传。
🔄 重试没生效
症状:POST 请求失败没有重试
原因:retry 默认 excludeMethods: ['POST','PUT','PATCH','DELETE'],写操作默认不自动重试(避免重复创建订单等副作用)。
解决:在请求级显式开启(请求级不受 excludeMethods 限制):
await axios.post('/api/idempotent-action', data, {
requestGuard: { retry: { attempts: 2 } }
});症状:返回 500 但没重试
原因:retry 默认只重试 [408,429,500,502,503,504]。如果错误没有 HTTP 状态码(如网络错误),需要看 errorCodes 白名单。
排查:用 canRetry 打印诊断信息,确认错误的状态码/错误码:
retry: {
attempts: 3,
canRetry(context) {
console.log('retry decision:', context.status, context.code, context.attempt);
return true; // 临时全量重试,观察日志
}
}症状:重试次数比预期多/少
原因:attempts 是总尝试次数(含首次),不是重试次数。attempts: 3 = 首次 + 2 次重试。
⚡ 短路错误被吞
症状:block 命中后,响应拦截器的错误处理没执行
这是预期行为。block 命中时请求根本没发出去,所以 axios.interceptors.response.use 的错误处理收不到。
解决:用 notify 出口处理短路错误的提示,或用请求级 .catch 分支处理。详见 错误处理模式。
症状:error.name 判断不匹配
原因:熔断错误的类名是 CircuitBreakerError,但 error.name 是 'RequestGuardCircuitBreakerError'(带前缀)。用类名当 name 判断会失败。
解决:统一用 error.name 字符串判别,详见 错误类型 - 类名陷阱。
🔄 reuse 等待方泄漏
症状:切换页面后,之前的 reuse 等待方一直挂起
原因:reuse 策略下,重复请求会挂起等待首次请求结果。如果页面切换时没有清理状态,等待方会一直挂着。
解决:在路由切换 / 组件销毁时调用 clearState(),会取消所有等待方(抛 RequestGuardCancelledError):
router.beforeEach(() => {
requestManager.clearState();
});🧹 clearRules 后请求仍被治理
症状:调用 clearRules() 后,某些请求仍被防重/熔断
原因:clearRules() 只切断后续请求的规则来源,不释放已在途的能力状态(如已登记的 inFlight 标记、已打开的熔断单元)。
解决:要彻底清空状态用 clearState();要恢复请求库原始行为用 uninstall()。三者区别见 RequestGuardController。
🔕 生产环境日志噪音
症状:生产环境控制台有 request-guard 的输出
原因:ConsoleRequestGuardLogger 默认 devOnly: true,但 dev 标识在跨端场景可能探测错误。
解决:显式传入 dev 标识:
logger: new ConsoleRequestGuardLogger({
dev: process.env.NODE_ENV !== 'production'
})或生产环境直接传 logger: null 关闭日志。
🔗 更多帮助
- 完整错误名一览:错误类型
- 事件与 payload 字段:事件与 payload 参考
- 错误处理模式:错误处理模式

