Axios中如何刷新Token?拦截器处理逻辑是否正确?
你的Axios响应拦截器401处理逻辑的问题与修正方案
你的代码在非401错误的处理上符合需求,但401场景的核心逻辑存在缺失,同时还有几个细节问题,下面逐一说明:
原代码的核心问题
- 未重新发起触发401的请求:你仅更新了默认headers,但没有重新执行最初触发401的请求,导致该请求会直接失败,无法自动重试。
- 并发请求会重复登录:如果同时有多个请求返回401,会多次调用
LoginAPI.API.Signin.run(),造成冗余的登录操作。 - 请求拦截器错误处理遗漏return:请求拦截器的错误回调里,
Promise.reject(error)没有加return,会导致错误无法正常传递到后续处理逻辑。
修正后的完整代码
import axios from "axios"; import { LoginAPI } from "../playwright/tests/login/login.api"; import { test } from "@playwright/test" import {configEnv} from "../config/config" test.beforeAll(async () => { await LoginAPI.API.Signin.run() }); const customAxios = axios.create({ baseURL: configEnv.apiBaseURL }); // 标记是否正在刷新token,避免并发请求重复触发登录 let isRefreshing = false; // 存储等待token刷新完成的请求队列 let requestQueue: any[] = []; customAxios.interceptors.request.use( async (config) => { if (config.headers) { config.headers['Authorization'] = `Bearer ${LoginAPI.States.token}`; } return config; }, (error) => { // 补充return,确保错误正常传递 return Promise.reject(error); } ); customAxios.interceptors.response.use( function(response) { return response; }, async function(error) { // 处理网络错误或无响应的异常情况 if (!error.response) { return Promise.reject(error.message || '网络请求异常'); } if (401 === error.response.status) { if (!isRefreshing) { isRefreshing = true; try { // 重新登录获取新token await LoginAPI.API.Signin.run(); const newToken = LoginAPI.States.token; // 更新全局默认headers customAxios.defaults.headers.common['Authorization'] = `Bearer ${newToken}`; // 重试队列中所有等待的请求 requestQueue.forEach(callback => callback(newToken)); requestQueue = []; } catch (loginError) { // 登录失败时,拒绝队列中所有请求 requestQueue.forEach(callback => callback(null)); requestQueue = []; return Promise.reject(loginError); } finally { isRefreshing = false; } } // 将当前请求加入队列,等待token刷新完成后重试 return new Promise((resolve, reject) => { requestQueue.push((newToken: string | null) => { if (newToken) { // 修改原请求的headers error.config.headers['Authorization'] = `Bearer ${newToken}`; // 重新发起原请求 resolve(customAxios(error.config)); } else { reject('登录失败,无法重试请求'); } }); }); } else { // 非401错误,返回error.response.data return Promise.reject(error.response.data); } } ); export default customAxios
关键修正点说明
- 添加token刷新锁与请求队列:用
isRefreshing避免并发请求重复触发登录,用requestQueue暂存等待刷新的请求,登录完成后统一重试,减少冗余操作。 - 重新发起原请求:token刷新成功后,修改原请求的Authorization头,调用
customAxios(error.config)重新发送请求,并通过Promise返回结果,让原请求的调用链能正常接收响应。 - 兼容网络错误场景:增加
!error.response的判断,处理网络异常等无响应状态的错误。 - 修复请求拦截器错误处理:在请求拦截器的错误回调中补充
return,确保错误能正常传递到后续的catch逻辑。
内容的提问来源于stack exchange,提问作者YusufOzt
相关产品推荐
相关产品推荐

