Skip to content

错误处理模式

request-guard 的错误分两类:短路错误(请求未发出)和真实错误(请求发出后失败)。它们的处理出口不同,混用会踩坑。本页给出选型与共存模式。

⚡ 两类错误的本质区别

短路错误真实错误
请求是否发出❌ 未发出✅ 已发出
是否经过 axios.interceptors.response.use❌ 不经过✅ 经过
触发能力duplicate block、circuitBreaker 熔断打开、duplicate 容量满retry 耗尽后返回的原始错误、网络错误、业务错误码
error.nameRequestGuard*Error原始错误名

短路错误不经过响应拦截器

duplicate block、cache evicted、circuitBreaker 熔断打开这类"请求未发出"的短路错误,不会进入 axios.interceptors.response.use 的错误处理,因为请求根本没发出去。duplicate ignore 命中不会产生错误,也不会进入 .catch();它返回的是永远 pending 的 Promise。

javascript
// ❌ 不可靠:短路错误不会进入这里
axios.interceptors.response.use(null, (error) => {
  if (error.name === 'RequestGuardBlockedError') { Toast.show(error.message); }
  return Promise.reject(error);
});

🎯 统一处理出口选型

出口适合场景优势局限
notify 回调guard 主动触发的用户提示(duplicate 命中、熔断拦截/状态变更)无需业务侧 catch,guard 触发的提示都能收口只处理 guard 主动提示,真实网络/业务错误不通用进入
请求级 .catch按错误类型分支处理error.name 精确判别,可改变后续逻辑每个调用点都要写
响应拦截器真实错误的统一处理集中管理收不到短路错误

👍 推荐组合

大多数项目推荐 notify(提示)+ 响应拦截器(真实错误) 双出口:

javascript
// 出口 1:notify 处理 guard 主动触发的用户提示
setupRequestGuard(axios, {
  notify: (payload) => {
    // duplicate ignore/block 命中、熔断拦截 都会进这里
    Toast.show(payload.message);
  }
});

// 出口 2:响应拦截器处理真实错误(短路错误不进这里)
axios.interceptors.response.use(
  (response) => response,
  (error) => {
    // 这里只会收到真实错误(网络错误、4xx/5xx、retry 耗尽后的原始错误)
    // 短路错误(RequestGuard*Error)不会进这里
    return Promise.reject(error);
  }
);

如果某些调用点需要按错误类型走不同逻辑,再在请求级 .catch 里用 error.name 分支:

javascript
try {
  await axios.post('/api/order', data);
} catch (error) {
  switch (error.name) {
    case 'RequestGuardBlockedError':
      // block 命中,已被 notify 提示,这里可静默或额外处理
      break;
    case 'RequestGuardCircuitBreakerError':
      // 熔断拦截,引导用户稍后重试
      router.push('/maintenance');
      break;
    default:
      // 真实错误,走业务统一处理
      throw error;
  }
}

🔄 retry 耗尽后的错误语义

retry 重试耗尽后,返回的是原始错误(不是 guard 包装的错误),所以:

  • error.name 是原始错误的 name(如 AxiosError),不是 RequestGuardRetryCancelledError
  • 响应拦截器收到这个错误(因为请求确实发出过)
  • retry 耗尽事件通过 retry.exhausted logger 事件观测,不触发 notify

RequestGuardRetryCancelledError 只在 clearState() 主动取消 waiting 状态的重试时抛出,属于短路错误语义。

🔗 与业务全局错误处理共存

如果你的项目已有全局错误处理(如响应拦截器里的统一 toast / 错误码路由),接入 guard 时注意:

  1. 短路错误不要在拦截器里处理——它们不经过拦截器。用 notify 出口接住。ignore 命中不是错误,不会进入任何错误处理分支。
  2. 真实错误保持原流程——guard 不包装真实错误,你的拦截器逻辑无需改动。
  3. 避免重复提示——如果 notify 已经提示了 block 命中,拦截器里的通用 toast 不要再对同一行为二次提示(短路错误本来就不会进拦截器,所以天然不冲突)。

📋 完整错误名一览

所有错误名及触发时机见 错误类型

基于 MIT 许可发布