React使用axios-auth-refresh处理Refresh Token过期原请求未等待问题
问题根因
- 首先
axios-auth-refresh的默认逻辑约定:如果你的refreshAuthLogic函数返回rejected状态的Promise,库会直接将原始请求的错误透传给上层调用方,也就是你遇到的getCourse调用处直接拿到错误的情况。你当前在refresh请求的catch分支直接返回了Promise.reject(err),正好触发了这个透传逻辑。 - 其次你发refresh-token请求用的是已经挂载了刷新拦截器的
API实例,如果refresh-token接口本身返回401,会再次触发刷新逻辑,造成死循环。 - 你注释了更新原始请求头的代码,就算refresh成功,重发的原始请求还是携带旧token,依然会返回401错误。
修复方案
修改后的完整代码如下:
import axios from "axios"; import createAuthRefreshInterceptor from 'axios-auth-refresh'; const API = axios.create({ baseURL }); API.interceptors.request.use( (config) => { config.headers["Authorization"] = getToken() || ""; return config; }, (error) => { return Promise.reject(error); } ); // 刷新鉴权逻辑的函数 const refreshAuthLogic = async (failedRequest) => { try { // 发刷新请求时加skipAuthRefresh,跳过当前拦截器,避免死循环 const response = await API.post("/refresh-token", { token: getRefreshToken("refresh_token"), }, { skipAuthRefresh: true }); const { token, refreshToken } = response.data; setToken(token); setRefreshToken(refreshToken); // 更新原始请求的头为新token,重发时才会生效 failedRequest.headers["Authorization"] = "Bearer " + token; return Promise.resolve(); } catch (err) { removeLocalStorageData(); fireSessionTimeoutAlert(err); // 5秒后重载页面,和你的sweet alert展示时长对齐 setTimeout(() => { window.location.reload(); }, 5000); // 这里不要返回reject,返回一个永久pending的Promise,阻止原始请求的错误透传 return new Promise(() => {}); } } // 注册拦截器 createAuthRefreshInterceptor(API, refreshAuthLogic);
修复说明
- 给refresh-token请求添加
skipAuthRefresh: true配置,避免刷新请求本身触发拦截器造成死循环。 - 放开原始请求头更新的逻辑,保证refresh成功后重发的请求携带新token。
- catch分支处理完登出逻辑后,返回永久pending的Promise,不会触发错误透传,上层getCourse的调用处不会拿到错误响应,等5秒弹窗结束后页面自动重载,完成登出流程。
内容的提问来源于stack exchange,提问作者Smith Dwayne
相关产品推荐
相关产品推荐

