Axios拦截器中Async/Await未等待请求完成就执行的问题排查
问题根因
核心问题出在fetchAuthToken的Promise链断裂,加上并发场景的状态标记逻辑有缺陷:
- 直接导致执行顺序错乱的原因:你在
/csrf-cookie请求的.then回调里调用apiClient.get("/token")时,没有return这个Promise实例。外层返回的Promise链会在CSRF请求完成后直接进入resolve状态,不会等待后续的/token请求执行完成,所以await fetchAuthToken()会提前返回,先打印then this,等token请求跑完才打印this,和预期顺序完全相反。 - 隐藏的并发问题:你用
isFetchingToken布尔值标记取token的状态,当页面同时发起多个业务请求时,第一个请求触发取token逻辑后,后续请求判断到isFetchingToken为true会直接返回false,不会等待token获取完成,最终会把false作为token塞到请求头里,导致鉴权失败。 - 其他逻辑隐患:空的
.catch会静默吞掉鉴权请求的报错,拦截器的错误回调没有returnPromise.reject(error),会吞掉请求错误,很难排查问题;直接给config.headers赋值会覆盖请求原本携带的其他自定义请求头。
修复方案
首先调整全局变量定义,用Promise缓存替代布尔标记,解决并发等待问题:
let authToken = checkLocalStorage("token", false); // 存储正在进行的取token请求Promise,替代原有的isFetchingToken标记 let authTokenPromise = null;
重写fetchAuthToken,保证Promise链完整,同时处理并发和错误逻辑:
function fetchAuthToken() { // 本地已有token直接返回 authToken = checkLocalStorage("token", false); if (authToken) return Promise.resolve(authToken); // 已有正在进行的取token请求,直接返回该Promise,避免重复请求 if (authTokenPromise) return authTokenPromise; authTokenPromise = apiClient .get("/csrf-cookie") .then(() => { // 必须return这个请求Promise,保证外层链等待token请求完成 return apiClient.get("/token"); }) .then((res) => { authToken = res.data.bearer_token; localStorage.setItem("token", JSON.stringify(authToken)); console.log("this"); return authToken; }) .catch((err) => { // 请求失败清空缓存,支持后续重试 authTokenPromise = null; // 抛出错误,不要静默吞错 throw err; }); return authTokenPromise; }
调整Axios请求拦截器逻辑,补全错误处理和请求头合并:
apiClient.interceptors.request.use( async (config) => { // 鉴权接口直接放行,不进入鉴权逻辑 if (config.url.includes("/csrf-cookie") || config.url.includes("/token")) { return config; } if (!authToken) { authToken = await fetchAuthToken(); console.log("then this"); } // 合并原有请求头,避免覆盖其他自定义头 config.headers = { ...config.headers, Authorization: `Bearer ${authToken}`, }; return config; }, (error) => { // 必须return rejected Promise,否则错误会被吞 return Promise.reject(error); } );
修复后执行顺序会完全符合预期:先打印this(token请求完成),再打印then this(await结束继续执行业务请求逻辑),同时并发场景下也不会出现重复请求、token未就绪就发业务请求的问题。
内容的提问来源于stack exchange,提问作者Frontendstrong
相关产品推荐
相关产品推荐

