多标签页共享session数据时storage事件触发无限循环如何解决
问题根因
- 处理
REQUESTING_SHARED_CREDENTIALS事件时,连续执行了localStorage.setItem('SHARING_AUTH')和localStorage.removeItem('SHARING_AUTH')两个写操作,每一次写localStorage都会触发所有同域其他标签页的storage事件。 - 打开标签页数量较多时,多个标签页会同时响应
REQUESTING_SHARED_CREDENTIALS事件、同时写入SHARING_AUTH,不同标签页的storage事件互相触发,形成无限循环。
修复方案
1. 增加当前页写入过滤,避免响应自身触发的storage事件
全局新增标记,过滤当前页面主动触发的storage写入事件:
// 全局变量,标记当前页是否正在操作共享storage let isCurrentPageWriting = false; // 存储监听处先过滤自身操作 window.addEventListener('storage', event => { if (isCurrentPageWriting) return; util.sessionStorageTransfer(event, sessionData, setSessionData, sessionLogout) }, false); // sessionStorageTransfer中修改写入逻辑 if (event.key === 'REQUESTING_SHARED_CREDENTIALS') { // 仅当前页有有效登录数据时才响应共享请求,避免空标签页乱写入 if (!sessionData?.token) return; isCurrentPageWriting = true; window.localStorage.setItem('SHARING_AUTH', JSON.stringify(sessionData)); window.localStorage.removeItem('SHARING_AUTH'); // 延迟重置标记,确保事件传播完成 setTimeout(() => isCurrentPageWriting = false, 0); }
2. 新增数据一致性校验,避免重复更新
处理SHARING_AUTH事件时先比对新旧数据,一致则跳过更新,减少不必要的触发:
if (event.key === 'SHARING_AUTH') { console.log(event.key); if (!event.newValue) return; const newSession = JSON.parse(event.newValue); // 数据和当前存储完全一致则不执行更新 if (JSON.stringify(newSession) === JSON.stringify(sessionData)) return; setSessionData(newSession); }
3. 增加防抖逻辑,避免短时间重复触发
给sessionStorageTransfer方法加短时间防抖,同时间段多个重复事件只会执行一次:
// util.js中新增防抖包装 const debounce = (fn, delay) => { let timer = null; return (...args) => { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); } } // 用防抖包装原有方法 sessionStorageTransfer: debounce(function(event, sessionData, setSessionData, sessionLogout) { // 原有逻辑不变 }, 50)
内容的提问来源于stack exchange,提问作者Rahul
相关产品推荐
相关产品推荐

