如何在用户关闭网站时可靠保存rrweb录制的会话事件数组?
可靠捕获页面卸载并保存rrweb会话事件的方案
核心思路
页面卸载时普通异步请求容易被浏览器中断,所以优先采用浏览器原生的不中断发送API,同时结合多事件监听覆盖各类卸载场景,确保会话事件能可靠存入数据库。
具体实现步骤
1. 优化rrweb事件存储逻辑
放弃每次事件触发都写入sessionStorage的方式,改用内存维护事件数组,仅定期备份到sessionStorage,减少序列化/反序列化的性能开销:
// 内存中维护会话事件数组 let sessionEvents = []; rrweb.record({ emit(event) { sessionEvents.push(event); // 每捕获50个事件就备份到sessionStorage,防止页面意外崩溃丢失数据 if (sessionEvents.length % 50 === 0) { sessionStorage.setItem('sessions_backup', JSON.stringify(sessionEvents)); } }, });
2. 封装可靠的保存函数
使用navigator.sendBeacon(优先)或带keepalive: true的fetch,这两个API能保证页面卸载时请求被完整发送:
function saveSessionEvents() { // 优先取内存中的事件,内存为空则从备份中读取 const events = sessionEvents.length > 0 ? sessionEvents : JSON.parse(sessionStorage.getItem('sessions_backup')) || []; if (events.length === 0) return; try { // 方案1:使用sendBeacon(兼容性更好,无阻塞) const blob = new Blob([JSON.stringify(events)], { type: 'application/json' }); navigator.sendBeacon('/api/save-session', blob); // 方案2:使用fetch with keepalive(支持自定义请求头) // fetch('/api/save-session', { // method: 'POST', // body: JSON.stringify(events), // headers: { 'Content-Type': 'application/json' }, // keepalive: true, // }); // 清空内存和备份数据 sessionEvents = []; sessionStorage.removeItem('sessions_backup'); } catch (err) { console.error('会话保存失败:', err); } }
3. 多事件监听覆盖卸载场景
同时监听多个事件,确保不同卸载操作都能触发保存:
// 监听页面可见性变化(切换标签、最小化、关闭页面都会触发) document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'hidden') { saveSessionEvents(); } }); // 监听beforeunload作为补充(部分浏览器关闭窗口时会触发) window.addEventListener('beforeunload', () => { saveSessionEvents(); }); // 监听unload事件(最后一道防线) window.addEventListener('unload', () => { saveSessionEvents(); }); // 处理logout按钮逻辑 document.getElementById('logout-btn').addEventListener('click', () => { saveSessionEvents(); // 执行后续logout操作 // ... });
4. 页面崩溃恢复优化
如果页面意外崩溃(如浏览器闪退),下次加载时自动恢复并保存未提交的备份事件:
window.addEventListener('load', () => { const backupEvents = JSON.parse(sessionStorage.getItem('sessions_backup')) || []; if (backupEvents.length > 0) { // 页面加载后异步保存备份数据 saveSessionEvents(); } });
关键说明
navigator.sendBeacon是最优方案,专门为页面卸载场景设计,不会阻塞页面关闭流程,兼容性覆盖绝大多数现代浏览器。visibilitychange事件能覆盖更多用户操作场景,比beforeunload更可靠,比如用户切换到其他标签页后再关闭浏览器的情况。- 内存存储+定期备份的方式,既保证性能,又避免意外情况下的数据丢失。
内容的提问来源于stack exchange,提问作者Daniel_Kamel
相关产品推荐
相关产品推荐

