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

如何使用Axios在刷新token请求完成前阻止其他接口请求发送

Axios刷新Token期间并发请求拦截实现方案

核心解决思路是通过全局状态标记刷新流程,同时缓存刷新期间的所有请求,待Token刷新完成后统一重发,避免多个请求重复触发刷新以及旧Token请求失败的问题。

改进后完整代码

import { AxiosResponse, AxiosPromise } from 'axios';

// 全局状态:标记当前是否正在刷新Token
let isRefreshing = false;
// 缓存队列:存储刷新期间收到的待重发请求
let requestQueue: Array<(token: string) => void> = [];

export const runRefreshToken = (errorCallback: () => void): void => {
  Axios.interceptors.response.use(
    (response: AxiosResponse<any>): AxiosResponse<any> => {
      return response;
    }, 
    async (error: any): Promise<any> => {
      const original = error.config;
      const loginVerification = !(original.url as string).startsWith("api/login");

      if (error.response && error.response.status === 401 && error.config && loginVerification) {
        // 未在刷新流程中,首次触发刷新
        if (!isRefreshing) {
          isRefreshing = true;
          try {
            // 调用刷新Token接口
            const refreshRes = await Axios.post("api/login/refresh-token");
            // 假设接口返回新的accessToken,更新全局请求头和本地存储的Token
            const newToken = refreshRes.data.accessToken;
            Axios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`;
            localStorage.setItem('token', newToken);

            // 刷新完成,重发队列中所有缓存的请求
            requestQueue.forEach(cb => cb(newToken));
            requestQueue = [];
            
            // 重发当前首次触发401的请求
            original.headers['Authorization'] = `Bearer ${newToken}`;
            return Axios(original);
          } catch (e) {
            // 刷新失败,触发回调跳登录
            errorCallback();
            requestQueue = [];
            if (original.url !== "api/login/verify-authentication") {
              history.push("/login");
            }
            return Promise.reject(e);
          } finally {
            // 重置刷新状态
            isRefreshing = false;
          }
        } else {
          // 正在刷新中,将当前请求加入缓存队列,返回Promise等待刷新完成后自动执行
          return new Promise(resolve => {
            requestQueue.push((newToken: string) => {
              original.headers['Authorization'] = `Bearer ${newToken}`;
              resolve(Axios(original));
            });
          });
        }
      }

      return Promise.reject(error);
    }
  );
}

逻辑说明

  • 新增isRefreshing全局标记,确保同一时间只会发起一次刷新Token的请求,避免重复调用刷新接口
  • 新增requestQueue队列,所有在刷新流程中触发的401请求都会被暂存到队列中,不会直接返回失败
  • Token刷新成功后,会先更新全局的请求头配置,再依次执行队列中缓存的所有请求,保证所有请求都使用最新的Token
  • 刷新失败时直接清空队列并跳转到登录页,避免无效请求堆积

注意事项

  • 刷新Token的接口本身需要排除在401拦截逻辑之外,避免出现循环拦截的问题
  • 刷新成功后必须同步更新本地存储的Token以及Axios的默认请求头,确保后续新发起的请求直接携带新Token
  • 如果项目中存在多个Axios实例,需要同步更新所有实例的请求头配置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 00:15:03