React中箭头函数自调用处理401重试请求出现死循环如何解决
死循环原因
两个核心问题:
- 无递归终止条件:只要接口持续返回401,递归就不会停止。常见触发场景是401分支的token刷新逻辑没有等待执行完成就发起重试,或是刷新后的新token没有正确注入请求头,导致每次重试都携带旧token,持续触发401响应。
- Promise链断裂:401分支内如果不
return递归调用的tokenGet,外层调用方的.then回调拿不到重试成功的返回值;如果加了return但没做终止判断,就会直接触发无限递归。
修复方案
首先给递归加上最大重试次数兜底,保证逻辑异常时也不会无限发请求;其次确保401处理逻辑执行完成后再发起重试,同时正确透传Promise链。
// 最大重试次数,根据业务需求调整,设1次就够覆盖常规token刷新场景 const MAX_RETRY = 1; const tokenGet = async (url, retryCount = 0) => { // 注意:请求配置里的鉴权头不要拿闭包缓存的旧token,每次请求实时从存储里取最新值 const requestConfig = { // 原有请求参数 headers: { Authorization: `Bearer ${window.localStorage.getItem('access_token') ?? ''}` } }; const res = await fetch(url, requestConfig); if (res.status === 401) { // 超过重试次数直接抛错终止 if (retryCount >= MAX_RETRY) { throw new Error('鉴权已失效,请重新登录'); } // 执行你原有的401处理逻辑:比如刷新token、清理无效状态等,一定要加await等执行完成 await handle401Logic(); // 重试时计数+1,必须return,把Promise结果透传给外层调用方 return tokenGet(url, retryCount + 1); } return res.json(); };
组件内调用部分补上错误捕获即可:
useEffect(() => { tokenGet(url) .then(data => { // 处理正常返回的业务数据 }) .catch(err => { // 处理请求失败、重试耗尽的场景,比如跳转登录页 console.error('请求异常', err); }); }, []);
关键注意事项
- 不要把token存在
tokenGet函数作用域的常量里缓存,否则刷新token后函数内拿到的永远是旧值,重试必然持续401触发死循环。 - 401分支的token刷新等异步逻辑必须加
await等待执行完成,再发起重试请求,否则重试时新token还未写入存储,还是会返回401。 - 必须保留最大重试次数的兜底逻辑,避免代码疏漏导致无限请求打垮服务或卡死页面。
内容的提问来源于stack exchange,提问作者Rafael Caixeta
相关产品推荐
相关产品推荐

