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

页面离开时上报RRWEB事件到服务端的失效问题如何解决

页面卸载场景rrweb数据上报优化方案

核心问题修正

你当前的实现存在三个直接影响上报成功率的问题:

  1. 未校验sendBeacon的返回值,当上报数据超过浏览器限制的64KB配额时,sendBeacon会直接返回false,请求不会被发送
  2. 触发上报后立即清空事件数组,异步上报逻辑可能还未读取到完整数据就被清空,导致上报内容为空
  3. 未给fetch请求添加keepalive属性,这是fetch请求在页面卸载时被取消的核心原因

具体优化实现

1. 重构上报逻辑,添加降级兼容

优先用性能更好的sendBeacon,发送失败时自动降级为带keepalive属性的fetch,同时新增失败数据本地缓存补发逻辑:

function sendRecording() {
  // 先拷贝当前事件数据到临时变量,避免原数组清空影响上报内容
  const currentEvents = [...sessionRecordingEvents]
  if (currentEvents.length === 0) return
  const params = new URLSearchParams({
    key : 'data',
    values : JSON.stringify(currentEvents)
  });
  // 优先调用sendBeacon
  const sendSuccess = navigator.sendBeacon(`${this.apiHost}/session`, params);
  if (!sendSuccess) {
    // 降级为带keepalive的fetch
    fetch(`${this.apiHost}/session`, {
      method: 'POST',
      body: params,
      keepalive: true,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      }
    }).catch(() => {
      // 请求失败时存入localStorage,下次页面加载时补发
      localStorage.setItem('rrweb_unsent', JSON.stringify(currentEvents))
    })
  }
}

2. 优化事件监听逻辑,添加防重复上报机制

同时新增页面启动时的本地缓存数据补发逻辑:

// 页面初始化时补发上次未发送的数据
const unsentData = localStorage.getItem('rrweb_unsent')
if (unsentData) {
  const params = new URLSearchParams({
    key : 'data',
    values : unsentData
  });
  fetch(`${this.apiHost}/session`, {
    method: 'POST',
    body: params
  }).then(() => localStorage.removeItem('rrweb_unsent'))
}

// 上报锁,防止短时间重复触发上报
let isSending = false
document.addEventListener("visibilitychange", function() {
  if (document.visibilityState === 'hidden') {
    if (isSending) return
    isSending = true
    sendRecording();
    sessionRecordingEvents = []
    // 300ms后重置锁,兼容用户切回页面的场景
    setTimeout(() => isSending = false, 300)
  } else {
    startRecording();
  }
});

额外优化建议

  • 平时采用增量上报策略,不要攒到页面卸载时一次性上报大量数据:每攒到10-20KB的rrweb事件就提前上报一次,页面卸载时仅上报最后剩余的小批量数据,避免超过64KB的配额限制
  • 不要监听unload事件,该事件在绝大多数移动端浏览器、Safari中不会被触发,visibilitychange已经可以覆盖所有页面切后台、关闭的场景
  • 如果上报接口是跨域地址,需要提前配置好对应的CORS规则,否则带keepalive的fetch请求也会被拦截

内容的提问来源于stack exchange,提问作者user103485

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 23:36:04