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

Axios响应拦截器onRejected无法重复请求问题排查

Axios拦截器刷新Token后重发请求失效问题解决

我用自定义Axios响应拦截器检测请求是否因Token过期被拒绝,刷新Token后本该重复原请求,但return axios.request(attachHeaders(originalRequest))代码完全没生效。Axios版本是1.1.3,相关代码、调试日志和尝试过的无效代码如下:

原代码

const baseAxios = axios.create();

baseAxios.defaults.baseURL = baseHttpUrl;

const attachHeaders = (request: AxiosRequestConfig): AxiosRequestConfig => {
  const accessToken = get(auth).access
  if (accessToken) {
    request.headers["Authorization"] = `Bearer ${accessToken}`;
  }
  return request
}

baseAxios.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    const originalRequest = error.config;

    // 检查请求是否被取消
    if (axios.isCancel(error)) {
      return Promise.reject(error);
    }
    // 检查错误是否与Token过期无关
    if (error.response.status !== 401 && error.response.data?.detail !== "expired_token") {
      return Promise.reject(error);
    }

    // 尝试刷新access_token
    if (await auth.refreshAccessToken()) {
      console.log("request again after token refresh")
      // 能打印上面的日志,但下面的代码好像没执行!
      console.log(attachHeaders(originalRequest))// 输出见下方
      return axios.request(attachHeaders(originalRequest));
    }

    return Promise.reject(error);
  }
)

调试日志

已确认新Token已正确附加到请求头,日志输出:

{
    "transitional": {
        "silentJSONParsing": true,
        "forcedJSONParsing": true,
        "clarifyTimeoutError": false
    },
    "transformRequest": [
        null
    ],
    "transformResponse": [
        null
    ],
    "timeout": 0,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1,
    "maxBodyLength": -1,
    "env": {},
    "headers": {
        "Accept": "application/json, text/plain, */*",
        "Authorization": "Bearer ACCES_TOKEN_STRING"
    },
    "baseURL": "http://localhost:1000",
    "method": "get",
    "url": "users/1"
}

尝试过的无效写法

以下写法均无法触发重发请求(日志能打印,但请求无响应):

return auth.refreshAccessToken().then(async (ok) => {
      if (ok) {
        console.log("request again after token refresh") // 能打印
        return await axios(attachHeaders(originalRequest)) // 无任何反应
      } else {
        return Promise.reject(error);
      }
    })
return auth.refreshAccessToken().then((ok) => {
      if (ok) {
        console.log("request again after token refresh") // 能打印
        return axios(attachHeaders(originalRequest)) // 无任何反应
      } else {
        return Promise.reject(error);
      }
    })

问题根源与解决步骤

1. 拦截器循环导致请求被静默拦截

重发的请求会再次进入响应拦截器,若不做标记,容易触发无限循环,最终导致请求被静默拒绝。给原请求添加重试标记:

async (error) => {
  const originalRequest = error.config;

  // 新增:检查是否已在重试,避免循环
  if (originalRequest._retry) {
    return Promise.reject(error);
  }
  originalRequest._retry = true;

  // 原有判断逻辑...
}

2. 使用自定义Axios实例而非全局axios

你创建了baseAxios实例并配置了baseURL等参数,但重发请求时用了全局axios,导致实例配置不生效,请求可能未按预期发送。修改重发代码:

// 把全局axios改成自定义的baseAxios
return baseAxios.request(attachHeaders(originalRequest));

3. 避免直接修改原请求对象

直接修改originalRequest.headers可能引发意外副作用,建议返回新的配置对象:

const attachHeaders = (request: AxiosRequestConfig): AxiosRequestConfig => {
  const accessToken = get(auth).access;
  if (!accessToken) return request;

  return {
    ...request,
    headers: {
      ...request.headers,
      Authorization: `Bearer ${accessToken}`
    }
  };
};

4. 捕获Token刷新的异常

若刷新Token过程中出现错误,需确保能正确捕获并抛出,避免静默失败:

try {
  const refreshSuccess = await auth.refreshAccessToken();
  if (refreshSuccess) {
    console.log("request again after token refresh");
    return baseAxios.request(attachHeaders(originalRequest));
  }
} catch (refreshError) {
  console.error("Token刷新失败:", refreshError);
}
return Promise.reject(error);

内容的提问来源于stack exchange,提问作者Sami Al-Subhi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:05:25