Skip to content

排错指南

常见误区与诊断方法。

🛡️ 防重没生效

症状:请求没有被去重

常见原因

  1. 规则没匹配到该请求 — 确认 rules 里的 method / url 真的命中了目标请求(注意 URL 正则是否包含 query)
  2. 能力未安装 — 用 core 按需入口时,确认 capabilities: [duplicate()] 已传入;全量入口默认已装
  3. 请求级配置关掉了 — 确认该请求的 requestGuard.duplicate 不是 false
  4. 方法被 excludeMethods 排除 — duplicate 默认排除 GET / OPTIONS / HEAD(读操作该重试/复用,不该阻断)。如果你期望 GET 也去重,需覆盖 excludeMethods 或在请求级显式开启

GET 默认不去重是预期行为

duplicate 默认 excludeMethods: ['GET','OPTIONS','HEAD'],因为读操作通常该用 reuse 复用或 retry 重试,而不是 block 阻断。要给 GET 开防重,在规则或 defaults 里把 excludeMethods 改成 [],或在请求级显式 requestGuard: { duplicate: true }(请求级不受 excludeMethods 限制)。

javascript
// 诊断:开启 debug 级日志观察
setupRequestGuard(axios, {
  logger: new ConsoleRequestGuardLogger({ devOnly: true, level: 'debug' })
});

症状:两个看起来不同的请求被误判为重复

原因:默认 compareFields 只比较 method/baseURL/url/params/data,如果你在 header 里传了租户 ID、时间戳等区分性字段,它们不参与判重。

解决:用 headerFields / compareHeaders 让指定 header 参与判重,或用 keyGenerator 完全自定义。

javascript
duplicate: {
  headerFields: ['X-Tenant-Id', 'X-Request-Id']
}

症状:FormData 上传总是被判为重复

原因:FormData 无法稳定序列化,默认占位符会把不同表单请求都视为相同。

解决:用 formDataResolver 自定义判重值。见 常见业务场景 - 文件上传

🔄 重试没生效

症状:POST 请求失败没有重试

原因:retry 默认 excludeMethods: ['POST','PUT','PATCH','DELETE'],写操作默认不自动重试(避免重复创建订单等副作用)。

解决:在请求级显式开启(请求级不受 excludeMethods 限制):

javascript
await axios.post('/api/idempotent-action', data, {
  requestGuard: { retry: { attempts: 2 } }
});

症状:返回 500 但没重试

原因:retry 默认只重试 [408,429,500,502,503,504]。如果错误没有 HTTP 状态码(如网络错误),需要看 errorCodes 白名单。

排查:用 canRetry 打印诊断信息,确认错误的状态码/错误码:

javascript
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):

javascript
router.beforeEach(() => {
  requestManager.clearState();
});

🧹 clearRules 后请求仍被治理

症状:调用 clearRules() 后,某些请求仍被防重/熔断

原因clearRules() 只切断后续请求的规则来源,不释放已在途的能力状态(如已登记的 inFlight 标记、已打开的熔断单元)。

解决:要彻底清空状态用 clearState();要恢复请求库原始行为用 uninstall()。三者区别见 RequestGuardController

🔕 生产环境日志噪音

症状:生产环境控制台有 request-guard 的输出

原因ConsoleRequestGuardLogger 默认 devOnly: true,但 dev 标识在跨端场景可能探测错误。

解决:显式传入 dev 标识:

javascript
logger: new ConsoleRequestGuardLogger({
  dev: process.env.NODE_ENV !== 'production'
})

或生产环境直接传 logger: null 关闭日志。

🔗 更多帮助

基于 MIT 许可发布