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

React使用axios-auth-refresh处理Refresh Token过期原请求未等待问题

问题根因

  • 首先axios-auth-refresh的默认逻辑约定:如果你的refreshAuthLogic函数返回rejected状态的Promise,库会直接将原始请求的错误透传给上层调用方,也就是你遇到的getCourse调用处直接拿到错误的情况。你当前在refresh请求的catch分支直接返回了Promise.reject(err),正好触发了这个透传逻辑。
  • 其次你发refresh-token请求用的是已经挂载了刷新拦截器的API实例,如果refresh-token接口本身返回401,会再次触发刷新逻辑,造成死循环。
  • 你注释了更新原始请求头的代码,就算refresh成功,重发的原始请求还是携带旧token,依然会返回401错误。

修复方案

修改后的完整代码如下:

import axios from "axios";
import createAuthRefreshInterceptor from 'axios-auth-refresh';

const API = axios.create({ baseURL });

API.interceptors.request.use(
  (config) => {
    config.headers["Authorization"] = getToken() || "";
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 刷新鉴权逻辑的函数
const refreshAuthLogic = async (failedRequest) => {
  try {
    // 发刷新请求时加skipAuthRefresh,跳过当前拦截器,避免死循环
    const response = await API.post("/refresh-token", {
      token: getRefreshToken("refresh_token"),
    }, {
      skipAuthRefresh: true
    });
    const { token, refreshToken } = response.data;
    setToken(token);
    setRefreshToken(refreshToken);
    // 更新原始请求的头为新token,重发时才会生效
    failedRequest.headers["Authorization"] = "Bearer " + token;
    return Promise.resolve();
  } catch (err) {
    removeLocalStorageData();
    fireSessionTimeoutAlert(err);
    // 5秒后重载页面,和你的sweet alert展示时长对齐
    setTimeout(() => {
      window.location.reload();
    }, 5000);
    // 这里不要返回reject,返回一个永久pending的Promise,阻止原始请求的错误透传
    return new Promise(() => {});
  }
}

// 注册拦截器
createAuthRefreshInterceptor(API, refreshAuthLogic);

修复说明

  • 给refresh-token请求添加skipAuthRefresh: true配置,避免刷新请求本身触发拦截器造成死循环。
  • 放开原始请求头更新的逻辑,保证refresh成功后重发的请求携带新token。
  • catch分支处理完登出逻辑后,返回永久pending的Promise,不会触发错误透传,上层getCourse的调用处不会拿到错误响应,等5秒弹窗结束后页面自动重载,完成登出流程。

内容的提问来源于stack exchange,提问作者Smith Dwayne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 19:39:00