You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Retrofit重试请求回调问题:全局捕获状态码后原始回调未触发

解决拦截器重试后原始Callback未触发的问题

嘿,我之前也踩过这个一模一样的坑!这种情况几乎都是因为你的拦截器在完成重试请求后,没有把结果正确传递回原始的请求Promise链,导致原始的.then()/.catch()或者async/await的后续逻辑完全收不到信号。下面给你几个关键的修复点:

  • 必须返回重试请求的Promise
    这是最核心的一点。不管你用的是Axios、Fetch还是自定义的请求库,拦截器的错误处理函数不能只执行重试请求就完事,一定要return这个重试请求的Promise,让它成为原始请求链的一部分。比如Axios的例子:

    axios.interceptors.response.use(
      (response) => response, // 正常响应直接返回给原始链
      async (error) => {
        const originalRequest = error.config;
        // 假设我们捕获401状态码并重试
        if (error.response.status === 401 && !originalRequest._retry) {
          originalRequest._retry = true; // 加个标记防止无限重试
          // 先执行你的指定操作,比如刷新token
          await refreshAuthToken();
          // 关键:返回重试后的请求Promise,把结果递回原始callback
          return axios(originalRequest);
        }
        // 如果不满足重试条件,把错误抛回原始链
        return Promise.reject(error);
      }
    );
    

    要是不return这个重试请求,原始的Promise就会卡在拦截器这里,永远触发不了后续的回调。

  • 避免覆盖原始请求的回调钩子
    有些时候我们会不小心修改originalRequest上的then/catch绑定,导致原始的callback被覆盖。这种情况要确保你只在拦截器里添加重试逻辑,不要去篡改原始请求自带的回调处理。

  • 自定义请求库的通用逻辑
    如果你是自己写的拦截器框架,核心思路还是一样:让拦截器的处理函数返回一个Promise,要么是正常响应,要么是重试后的请求Promise。比如基于Fetch的封装:

    const enhancedFetch = async (url, options = {}) => {
      let response = await fetch(url, options);
      // 捕获目标状态码
      if (response.status === 401 && !options._retry) {
        options._retry = true;
        // 执行指定操作,比如更新请求头里的token
        options.headers = { ...options.headers, Authorization: `Bearer ${newToken}` };
        // 返回重试请求,让原始调用者拿到结果
        return enhancedFetch(url, options);
      }
      return response;
    };
    

    这样你调用enhancedFetch(...).then(res => { /* 这里就能触发原始callback了 */ })就完全正常了。

简单来说,就是要让拦截器成为请求Promise链的一环,而不是一个独立的分支——重试后的结果必须沿着链传递回去,原始的callback才能感知到请求完成。

内容的提问来源于stack exchange,提问作者Lena Bru

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 03:33:18