You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在用户关闭网站时可靠保存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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 12:05:20