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

SPA中Navigator.sendBeacon()请求堆叠问题排查与解决咨询

解决方案:移除组件卸载时的监听器

问题的核心是SPA页面导航时组件未清理事件监听器:每次进入视频页面组件,你都会添加一个页面可见性变化的监听器,但组件卸载(Inertia导航离开)时没有移除它,导致监听器不断累积。当页面隐藏(切换标签/关闭)时,所有累积的监听器都会触发,发送对应数量的Beacon请求。

修正后的代码示例

在Vue 3组件中,利用组件生命周期钩子管理监听器的添加与移除:

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const props = defineProps(['currentLesson'])
const video = ref(null)

const sendBeacon = () => {
  // 修正模板字符串:用反引号解析变量
  const url = `/api/video/${props.currentLesson.media.id}/progress`
  const timeLine = {
    progress: video.value.currentTime,
    duration: video.value.duration
  }

  // 标准判断页面是否隐藏
  if (!document.hidden) return

  const data = new Blob([JSON.stringify(timeLine)], { type: 'application/json' })
  navigator.sendBeacon(url, data)
}

onMounted(() => {
  // 监听页面可见性变化事件(修正事件名:visibilitychange)
  document.addEventListener('visibilitychange', sendBeacon)
})

onUnmounted(() => {
  // 组件卸载时必须移除监听器,避免累积
  document.removeEventListener('visibilitychange', sendBeacon)
})
</script>

关键说明

  1. 清理监听器:在onUnmounted钩子中移除监听器,是解决请求堆叠的核心操作。Inertia导航离开页面时,组件会执行卸载钩子,此时移除监听器就能避免后续触发多余请求。
  2. 修正模板字符串:原代码中用单引号包裹URL会导致变量无法解析,改为反引号才能正确生成对应视频的进度统计接口地址。
  3. 标准事件与判断:使用Page Visibility API的visibilitychange事件和document.hidden状态判断,替代原代码中可能错误的statechange事件,确保逻辑符合规范。

额外注意事项

  • 不要在全局作用域添加监听器,必须绑定到单个视频组件的生命周期内,避免跨页面的监听器干扰。
  • 如果使用Inertia的preserveState或partialReload特性,要确保组件卸载逻辑依然正常执行,避免监听器残留。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 12:17:25