React Native过期Token并发请求处理问题求助
解决React Native多并行请求下Token重复刷新问题
你的核心问题是多个并行请求同时触发了Token刷新逻辑,原因是refreshAuthToken的锁机制没有真正拦住后续请求——当第一个请求还在刷新Token时,userAccess状态还没更新,后续请求进入getCredentials时依然判断Token过期,从而重复调用refreshToken,导致旧的refreshToken被作废后,后续请求再用它刷新就会报错。
修正方案
1. 把刷新锁逻辑移到getCredentials内部
让getCredentials自身成为单入口,确保同一时间只有一个刷新请求发起,其他请求复用同一个刷新Promise:
// 模块级/全局变量,避免组件重渲染时被重置 let refreshTokenPromise: Promise<string> | null = null; const getCredentials = useCallback(async () => { // 优先复用正在进行的刷新请求 if (refreshTokenPromise) { return await refreshTokenPromise; } const currentUnixTimestamp = moment().unix(); if (userAccess.expirationTimeStamp < currentUnixTimestamp) { console.log('refreshing token', userAccess.accessObject?.refreshToken); // 赋值全局Promise,让所有后续请求等待同一个任务 refreshTokenPromise = refreshToken() .then(newToken => { // 关键:刷新成功后必须更新userAccess状态 // 这里需要调用更新userAccess的方法(比如setUserAccess),把新的token和过期时间存进去 return newToken; }) .finally(() => { // 刷新完成后清空Promise,允许下次正常触发刷新 refreshTokenPromise = null; }); return await refreshTokenPromise; } return userAccess.accessObject?.accessToken || ''; }, [userAccess, refreshToken]);
2. 确保Axios拦截器正确调用getCredentials
所有请求必须通过拦截器统一获取Token,避免绕开锁逻辑:
axiosInstance.interceptors.request.use(async (config) => { const token = await getCredentials(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; });
3. 处理刷新失败的边界情况
如果刷新Token失败(比如refreshToken本身过期),需要及时清除本地凭证并跳转登录,避免无限循环:
refreshTokenPromise = refreshToken() .then(newToken => { // 更新userAccess状态 return newToken; }) .catch(error => { // 刷新失败:清除本地存储的凭证,跳转到登录页 clearCredentials(); navigation.navigate('Login'); throw error; // 抛出错误让请求拦截器捕获 }) .finally(() => { refreshTokenPromise = null; });
为什么原代码无效?
原代码中refreshAuthToken的锁是在调用getCredentials之前,但多个并行请求会同时进入refreshAuthToken——此时refreshTokenPromise还未被赋值,所以多个请求都会执行getCredentials。而此时userAccess还是旧的过期状态,每个getCredentials都会判断Token过期,进而重复触发refreshToken,导致后续请求使用已作废的refreshToken报错。
内容的提问来源于stack exchange,提问作者JamesG
相关产品推荐
相关产品推荐

