如何使用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
相关产品推荐
相关产品推荐

