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

Axios刷新Token成功后无法重发失败请求求助

Axios 401刷新Token后无法重发原请求的修复方案

代码核心问题及修复点

  • 拼写错误导致订阅回调失效:代码里的onRrefreshed是拼写错误,应为onRefreshed,这个函数负责通知排队的请求Token已刷新,拼写错误会导致后续等待的请求无法触发重发。
  • 重发请求用错Axios实例:排队请求的处理逻辑里用了全局axios重发原请求,但原请求是通过loggedAxios实例发起的,改用loggedAxios才能保留实例的拦截器和配置。
  • FailedQueue未执行排队请求:刷新Token成功后直接清空队列,没有遍历执行队列里的等待请求,需要调用每个队列回调并传入新Token。
  • Loop变量未重置:loop用于限制刷新次数,但刷新完成后未重置,会导致后续401错误无法触发刷新逻辑,需在finally里重置为0。
  • 冗余Promise包装:成功响应的回调不需要额外包装Promise,直接返回response即可。

修正后的完整代码

/**
 * Axios Response Handler
 */
// 初始化全局控制变量
let isRefreshing = false;
let failedQueue = [];
let loop = 0;

// 订阅Token刷新完成的回调函数
const subscribeTokenRefresh = (callback) => {
  failedQueue.push(callback);
};

// 通知所有排队请求Token已更新
const onRefreshed = (token) => {
  failedQueue.forEach(callback => callback(token));
  failedQueue = [];
};

loggedAxios.interceptors.response.use(
  (response) => response,
  (error) => {
    const originalConfig = error.config;
    let auths = JSON.parse(localStorage.getItem("htAuth"));

    // Access Token过期处理逻辑
    if (error?.response?.status === 401 && auths !== undefined && loop < 1) {
      const rtkn = localStorage.getItem("rTkn");

      if (!isRefreshing) {
        loop++;
        isRefreshing = true;
        return new Promise((resolve, reject) => {
          const payload = { refresh: rtkn };
          refreshTokenApi(payload)
            .then((res) => {
              const newAccessToken = res.data?.access;
              // 更新实例默认请求头
              loggedAxios.defaults.headers.common["Authorization"] = `Bearer ${newAccessToken}`;
              // 更新原请求的请求头
              originalConfig.headers["Authorization"] = `Bearer ${newAccessToken}`;
              // 更新本地存储的Token
              auths.token = newAccessToken;
              localStorage.setItem("htAuth", JSON.stringify(auths));
              // 通知所有排队请求重发
              onRefreshed(newAccessToken);
              // 重发原请求
              resolve(loggedAxios(originalConfig));
            })
            .catch((err) => {
              // 刷新失败清空队列,拒绝所有请求
              failedQueue = [];
              reject(err);
            })
            .finally(() => {
              isRefreshing = false;
              loop = 0; // 重置loop,允许后续触发刷新
            });
        });
      }

      // 将当前请求加入等待队列
      return new Promise((resolve) => {
        subscribeTokenRefresh((token) => {
          originalConfig.headers.Authorization = `Bearer ${token}`;
          resolve(loggedAxios(originalConfig));
        });
      });
    }
    return Promise.reject(error);
  }
);

快速测试技巧(不用等Token过期)

  1. 打开浏览器控制台(F12),进入Application -> Local Storage
  2. 找到htAuth项,把里面的token字段改成任意无效字符串(比如乱码)
  3. 发起请求,此时会触发401错误,直接测试刷新Token和重发请求的流程

内容的提问来源于stack exchange,提问作者Soonang Rai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:05:17