Axios响应拦截器onRejected无法重复请求问题排查
Axios拦截器刷新Token后重发请求失效问题解决
我用自定义Axios响应拦截器检测请求是否因Token过期被拒绝,刷新Token后本该重复原请求,但return axios.request(attachHeaders(originalRequest))代码完全没生效。Axios版本是1.1.3,相关代码、调试日志和尝试过的无效代码如下:
原代码
const baseAxios = axios.create(); baseAxios.defaults.baseURL = baseHttpUrl; const attachHeaders = (request: AxiosRequestConfig): AxiosRequestConfig => { const accessToken = get(auth).access if (accessToken) { request.headers["Authorization"] = `Bearer ${accessToken}`; } return request } baseAxios.interceptors.response.use( (response) => { return response; }, async (error) => { const originalRequest = error.config; // 检查请求是否被取消 if (axios.isCancel(error)) { return Promise.reject(error); } // 检查错误是否与Token过期无关 if (error.response.status !== 401 && error.response.data?.detail !== "expired_token") { return Promise.reject(error); } // 尝试刷新access_token if (await auth.refreshAccessToken()) { console.log("request again after token refresh") // 能打印上面的日志,但下面的代码好像没执行! console.log(attachHeaders(originalRequest))// 输出见下方 return axios.request(attachHeaders(originalRequest)); } return Promise.reject(error); } )
调试日志
已确认新Token已正确附加到请求头,日志输出:
{ "transitional": { "silentJSONParsing": true, "forcedJSONParsing": true, "clarifyTimeoutError": false }, "transformRequest": [ null ], "transformResponse": [ null ], "timeout": 0, "xsrfCookieName": "XSRF-TOKEN", "xsrfHeaderName": "X-XSRF-TOKEN", "maxContentLength": -1, "maxBodyLength": -1, "env": {}, "headers": { "Accept": "application/json, text/plain, */*", "Authorization": "Bearer ACCES_TOKEN_STRING" }, "baseURL": "http://localhost:1000", "method": "get", "url": "users/1" }
尝试过的无效写法
以下写法均无法触发重发请求(日志能打印,但请求无响应):
return auth.refreshAccessToken().then(async (ok) => { if (ok) { console.log("request again after token refresh") // 能打印 return await axios(attachHeaders(originalRequest)) // 无任何反应 } else { return Promise.reject(error); } })
return auth.refreshAccessToken().then((ok) => { if (ok) { console.log("request again after token refresh") // 能打印 return axios(attachHeaders(originalRequest)) // 无任何反应 } else { return Promise.reject(error); } })
问题根源与解决步骤
1. 拦截器循环导致请求被静默拦截
重发的请求会再次进入响应拦截器,若不做标记,容易触发无限循环,最终导致请求被静默拒绝。给原请求添加重试标记:
async (error) => { const originalRequest = error.config; // 新增:检查是否已在重试,避免循环 if (originalRequest._retry) { return Promise.reject(error); } originalRequest._retry = true; // 原有判断逻辑... }
2. 使用自定义Axios实例而非全局axios
你创建了baseAxios实例并配置了baseURL等参数,但重发请求时用了全局axios,导致实例配置不生效,请求可能未按预期发送。修改重发代码:
// 把全局axios改成自定义的baseAxios return baseAxios.request(attachHeaders(originalRequest));
3. 避免直接修改原请求对象
直接修改originalRequest.headers可能引发意外副作用,建议返回新的配置对象:
const attachHeaders = (request: AxiosRequestConfig): AxiosRequestConfig => { const accessToken = get(auth).access; if (!accessToken) return request; return { ...request, headers: { ...request.headers, Authorization: `Bearer ${accessToken}` } }; };
4. 捕获Token刷新的异常
若刷新Token过程中出现错误,需确保能正确捕获并抛出,避免静默失败:
try { const refreshSuccess = await auth.refreshAccessToken(); if (refreshSuccess) { console.log("request again after token refresh"); return baseAxios.request(attachHeaders(originalRequest)); } } catch (refreshError) { console.error("Token刷新失败:", refreshError); } return Promise.reject(error);
内容的提问来源于stack exchange,提问作者Sami Al-Subhi
相关产品推荐
相关产品推荐

