React中localStorage缓存API响应的Token过期清理方案咨询
解决方案
你这个问题核心就是把本地缓存设成了永久有效,只要有缓存就完全跳过网络请求,等于把token过期校验的唯一触发路径给堵死了,根本不需要额外加校验接口、也不用换存储方案,改几行代码就能解决。
具体改法
- 第一步:给缓存加过期时间,别永久存
你token有效期是1小时,缓存有效期设得比token短就行,比如50分钟。存缓存的时候不要只存接口返回的原始数据,额外包一层存个过期时间戳:// 原来的localStorage.setItem('rnList', JSON.stringify(response.data)); 改成下面的 const cachePack = { expireAt: Date.now() + 50 * 60 * 1000, // 50分钟后过期 payload: response.data } localStorage.setItem('rnList', JSON.stringify(cachePack)); - 第二步:读缓存的时候先校验有效期
拿到本地缓存先解包看有没有过期,没过期再走原来的setOldData逻辑读缓存,过期了直接删掉缓存,正常走接口请求流程:if (window.localStorage !== undefined) { const cacheStr = window.localStorage.getItem('rnList'); let useCache = false; if (cacheStr) { try { const cache = JSON.parse(cacheStr); if (cache.expireAt > Date.now()) { // 缓存有效,用旧数据 setOldData(JSON.stringify(cache.payload)); useCache = true; } else { // 缓存过期,直接清掉 window.localStorage.removeItem('rnList'); } } catch(e) { // 缓存格式损坏也直接清 window.localStorage.removeItem('rnList'); } } if (useCache) { hideLoader(); } else { // 这里放你原来的RNService.getRNList请求逻辑即可 } } - 第三步:把401处理逻辑抽成全局拦截器
不要在单个接口的catch里写401处理,给axios加个全局响应拦截器,所有接口只要返回401状态码,统一清空localStorage里所有业务缓存(包括列表缓存、token、用户信息),直接跳登录页。这样不管是哪个接口触发了token过期,都能把脏数据清干净,不会漏。
对你两个思路的说明
- 额外加token校验接口完全没必要:你本来就要拉列表数据,缓存过期后自然会发起列表请求,顺带就完成了token校验,多发一次校验请求纯属于浪费流量。
- 换sessionStorage、Redux解决不了根本问题:sessionStorage只是标签页关闭才清空,只要你标签页开着超过1小时,一样会遇到有缓存不发请求、检测不到token过期的问题;Redux存在内存里,刷新页面就丢,确实不会有永久缓存的问题,但你本来做缓存就是为了减少重复请求、提升加载速度,换Redux等于每次刷新都要重新拉接口,浪费了缓存的价值。
额外注意的坑
- 你现在代码里
hideLoader()的调用位置有问题,读缓存分支、接口请求成功、接口请求失败三个分支都要记得调用,不然容易出现loading遮罩一直关不掉的bug。 - 不管是用户手动点登出,还是401触发的自动登出,一定要把所有业务相关的本地缓存都清干净,别只清token,不然下次登录其他账号,可能会读到之前账号存的列表数据,有数据泄露风险。
- 要是想做更好的用户体验,可以加个后台静默更新逻辑:就算缓存过期了,也先把旧数据渲染出来,后台悄悄发请求拉新数据替换,不用弹全屏loading,用户完全感知不到加载过程,就算静默请求触发401,再跳登录就行。
内容的提问来源于stack exchange,提问作者NoDiggityNoDoubt
相关产品推荐
相关产品推荐

