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;
关键细节说明
- 避免重复刷新:
isRefreshing变量确保同一时间只有一个刷新token的请求发起,防止后端收到重复的刷新请求。 - 请求队列处理:当多个请求同时触发401时,除第一个请求发起刷新外,其余请求都加入队列,等新token获取后统一重试。
- 标记重试状态:给
originalRequest添加_retry属性,防止请求重试后再次触发401拦截,造成死循环。 - 更新默认请求头:刷新成功后更新Axios实例的默认Authorization头,后续新发起的请求自动使用新token。
这样处理后,用户无需重复操作,所有因token过期失败的请求都会自动重试,完全在全局拦截器中处理,不需要在组件中单独写逻辑。
内容的提问来源于stack exchange,提问作者seagulls0125
相关产品推荐
相关产品推荐

