Axios刷新Token成功后无法重发失败请求求助
Axios 401刷新Token后无法重发原请求的修复方案
代码核心问题及修复点
- 拼写错误导致订阅回调失效:代码里的
onRrefreshed是拼写错误,应为onRefreshed,这个函数负责通知排队的请求Token已刷新,拼写错误会导致后续等待的请求无法触发重发。 - 重发请求用错Axios实例:排队请求的处理逻辑里用了全局
axios重发原请求,但原请求是通过loggedAxios实例发起的,改用loggedAxios才能保留实例的拦截器和配置。 - FailedQueue未执行排队请求:刷新Token成功后直接清空队列,没有遍历执行队列里的等待请求,需要调用每个队列回调并传入新Token。
- Loop变量未重置:
loop用于限制刷新次数,但刷新完成后未重置,会导致后续401错误无法触发刷新逻辑,需在finally里重置为0。 - 冗余Promise包装:成功响应的回调不需要额外包装Promise,直接返回
response即可。
修正后的完整代码
/** * Axios Response Handler */ // 初始化全局控制变量 let isRefreshing = false; let failedQueue = []; let loop = 0; // 订阅Token刷新完成的回调函数 const subscribeTokenRefresh = (callback) => { failedQueue.push(callback); }; // 通知所有排队请求Token已更新 const onRefreshed = (token) => { failedQueue.forEach(callback => callback(token)); failedQueue = []; }; loggedAxios.interceptors.response.use( (response) => response, (error) => { const originalConfig = error.config; let auths = JSON.parse(localStorage.getItem("htAuth")); // Access Token过期处理逻辑 if (error?.response?.status === 401 && auths !== undefined && loop < 1) { const rtkn = localStorage.getItem("rTkn"); if (!isRefreshing) { loop++; isRefreshing = true; return new Promise((resolve, reject) => { const payload = { refresh: rtkn }; refreshTokenApi(payload) .then((res) => { const newAccessToken = res.data?.access; // 更新实例默认请求头 loggedAxios.defaults.headers.common["Authorization"] = `Bearer ${newAccessToken}`; // 更新原请求的请求头 originalConfig.headers["Authorization"] = `Bearer ${newAccessToken}`; // 更新本地存储的Token auths.token = newAccessToken; localStorage.setItem("htAuth", JSON.stringify(auths)); // 通知所有排队请求重发 onRefreshed(newAccessToken); // 重发原请求 resolve(loggedAxios(originalConfig)); }) .catch((err) => { // 刷新失败清空队列,拒绝所有请求 failedQueue = []; reject(err); }) .finally(() => { isRefreshing = false; loop = 0; // 重置loop,允许后续触发刷新 }); }); } // 将当前请求加入等待队列 return new Promise((resolve) => { subscribeTokenRefresh((token) => { originalConfig.headers.Authorization = `Bearer ${token}`; resolve(loggedAxios(originalConfig)); }); }); } return Promise.reject(error); } );
快速测试技巧(不用等Token过期)
- 打开浏览器控制台(F12),进入
Application->Local Storage - 找到
htAuth项,把里面的token字段改成任意无效字符串(比如乱码) - 发起请求,此时会触发401错误,直接测试刷新Token和重发请求的流程
内容的提问来源于stack exchange,提问作者Soonang Rai
相关产品推荐
相关产品推荐

