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

React JWT场景下,Axios拦截器如何自动重调失效API?

解决Axios拦截器401刷新token后自动重试请求的问题

要实现自动重试失败请求,核心是在拦截器中缓存失败请求,等新token获取后批量重试,同时避免并发请求重复触发token刷新。以下是具体实现方案:

核心实现步骤

  • 用一个变量标记是否正在刷新token,防止多个401请求重复触发刷新逻辑
  • 用一个队列存储等待重试的失败请求,token刷新完成后统一处理
  • 拦截401响应时,根据刷新状态决定是发起刷新请求,还是将请求加入队列
  • 刷新成功后更新token,遍历队列重新发起所有缓存的请求

代码示例

首先创建Axios实例并配置拦截器:

import axios from 'axios';

// 创建Axios实例
const api = axios.create({
  baseURL: '/api',
});

// 标记是否正在刷新token
let isRefreshing = false;
// 存储等待重试的请求队列
let requestQueue = [];

// 请求拦截器:给每个请求带上当前的access token
api.interceptors.request.use(
  (config) => {
    const accessToken = localStorage.getItem('accessToken');
    if (accessToken) {
      config.headers.Authorization = `Bearer ${accessToken}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

// 响应拦截器
api.interceptors.response.use(
  (response) => response,
  async (error) => {
    const originalRequest = error.config;
    // 捕获401状态码,且不是刷新token的请求本身(避免死循环)
    if (error.response?.status === 401 && !originalRequest._retry) {
      // 标记当前请求已进入重试流程
      originalRequest._retry = true;

      if (!isRefreshing) {
        isRefreshing = true;
        try {
          // 调用刷新token的接口
          const refreshToken = localStorage.getItem('refreshToken');
          const res = await axios.post('/api/auth/refresh', { refreshToken });
          const newAccessToken = res.data.accessToken;
          
          // 更新本地存储的token
          localStorage.setItem('accessToken', newAccessToken);
          
          // 更新Axios实例的默认请求头(后续请求自动带新token)
          api.defaults.headers.common.Authorization = `Bearer ${newAccessToken}`;
          
          // 重试队列中所有等待的请求
          requestQueue.forEach(callback => callback(newAccessToken));
          requestQueue = [];
        } catch (refreshError) {
          // 刷新token失败,跳转到登录页,清空本地token
          localStorage.removeItem('accessToken');
          localStorage.removeItem('refreshToken');
          window.location.href = '/login';
          return Promise.reject(refreshError);
        } finally {
          isRefreshing = false;
        }
      }

      // 返回Promise,等待token刷新完成后重试原请求
      return new Promise((resolve) => {
        requestQueue.push((token) => {
          originalRequest.headers.Authorization = `Bearer ${token}`;
          resolve(api(originalRequest));
        });
      });
    }

    // 非401错误,直接抛出
    return Promise.reject(error);
  }
);

export default api;

关键细节说明

  1. 避免重复刷新:isRefreshing变量确保同一时间只有一个刷新token的请求发起,防止后端收到重复的刷新请求。
  2. 请求队列处理:当多个请求同时触发401时,除第一个请求发起刷新外,其余请求都加入队列,等新token获取后统一重试。
  3. 标记重试状态:给originalRequest添加_retry属性,防止请求重试后再次触发401拦截,造成死循环。
  4. 更新默认请求头:刷新成功后更新Axios实例的默认Authorization头,后续新发起的请求自动使用新token。

这样处理后,用户无需重复操作,所有因token过期失败的请求都会自动重试,完全在全局拦截器中处理,不需要在组件中单独写逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 20:15:37