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

Axios请求拦截器遇401响应未触发错误回调,无法执行Token刷新

问题分析与修复方案

核心问题

你把响应拦截器错误地注册成了请求拦截器,后端返回的401属于响应阶段的错误,只会触发axios.interceptors.response.use的错误回调,而非请求拦截器。这就是你看不到console.log输出的根本原因。

具体修复步骤

  1. 修正拦截器类型
    把第二个axios.interceptors.request.use改成axios.interceptors.response.use,才能捕获响应阶段的401错误。

  2. 修复请求拦截器的错误回调
    第一个请求拦截器的错误回调里,仅写了Promise.reject(error)但未添加return,导致错误无法正确向下传递,必须补上return。

  3. 完善Token刷新逻辑
    在响应拦截器中检测到401时,调用refreshToken接口获取新Token,更新本地存储后重新发起原请求。同时添加标记避免重复刷新(多个请求同时触发401时,只执行一次刷新)。

  4. 优化Headers设置方式
    直接赋值config.headers = {...}会覆盖axios默认请求头,改用Object.assign合并,避免丢失必要的默认头信息。

修复后的完整代码

import axios from "axios";

// 请求拦截器:添加Token到请求头
axios.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem("_token") || "";
    if (token) {
      // 合并headers,保留默认值
      config.headers = Object.assign({}, config.headers, {
        "Content-Type": "application/json",
        Accept: "application/json",
        Authorization: `Bearer ${token}`,
      });
    } else {
      console.log("还没有Token...");
    }
    return config;
  },
  (error) => {
    console.log("请求阶段错误:", error?.response?.status);
    return Promise.reject(error); // 必须return,否则错误无法传递
  }
);

// 刷新Token接口
const refreshToken = async () => {
  try {
    const resp = await axios.get("auth/refresh");
    localStorage.setItem("_token", resp.data.token); // 假设返回的新Token字段为token
    return resp.data.token;
  } catch (e) {
    console.log("刷新Token失败:", e);
    // 刷新失败,清除本地Token并跳转登录页
    localStorage.removeItem("_token");
    window.location.href = "/login";
    return Promise.reject(e);
  }
};

// 响应拦截器:处理401错误,刷新Token并重发请求
axios.interceptors.response.use(
  (response) => {
    return response;
  },
  async (error) => {
    console.log("响应错误:", error?.response);
    const originalRequest = error.config;

    // 检测401且未尝试过刷新Token,避免循环刷新
    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const newToken = await refreshToken();
        // 更新原请求的Authorization头
        originalRequest.headers.Authorization = `Bearer ${newToken}`;
        // 重新发起原请求
        return axios(originalRequest);
      } catch (refreshError) {
        return Promise.reject(refreshError);
      }
    }

    return Promise.reject(error);
  }
);

export default axios;

额外说明

  • _retry标记用于防止Token刷新失败后,请求陷入无限循环。
  • 刷新Token失败后,建议清除本地Token并跳转登录页,引导用户重新登录。
  • Access-Control-Allow-Origin是后端设置的响应头,前端无需在请求头中添加,添加后也无效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 10:52:45