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

页面关闭时如何可靠保存视频播放进度至数据库?

解决页面关闭前无法完成异步保存视频进度的问题

问题根源

beforeunload 事件的回调是同步执行逻辑,即便用了 async/await,浏览器也不会等待异步操作完成就会终止页面进程,导致你的 fetch 请求大概率被中断。

正确实现方式

方法1:使用 navigator.sendBeacon()

这是浏览器专为「页面卸载前发送数据」场景设计的API,它会异步发起请求,但浏览器会保证请求完成后再关闭页面,无需等待响应结果,适合仅需提交数据的场景。

修改代码如下:

const handleBeforeUnload = () => {
  save_timestamp();
};

const save_timestamp = () => {
  const v: IResumeVideo = {
    seconds: timeline.current,
    video_id: video_id
  };
  // 将数据转为Blob格式适配sendBeacon要求
  const blob = new Blob([JSON.stringify(v)], { type: 'application/json' });
  navigator.sendBeacon('/api/save_video', blob);
};

// 在React组件的useEffect中绑定/解绑事件
useEffect(() => {
  window.addEventListener('beforeunload', handleBeforeUnload);
  return () => {
    window.removeEventListener('beforeunload', handleBeforeUnload);
  };
}, [timeline.current, video_id]); // 根据实际依赖项调整

方法2:使用 fetch 的 keepalive 选项

如果需要对请求响应做处理(尽管页面关闭后处理响应意义有限),可以给 fetch 添加 keepalive: true 参数,强制浏览器维持请求直到完成:

const save_timestamp = async () => {
  const v: IResumeVideo = {
    seconds: timeline.current,
    video_id: video_id
  };
  await fetch('/api/save_video', {
    method: 'POST',
    body: JSON.stringify(v),
    headers: {
      'Content-Type': 'application/json'
    },
    keepalive: true // 核心参数,确保请求不被中断
  });
};

注意事项

  • navigator.sendBeacon() 不支持自定义请求头(仅少数默认头可用),若后端要求特定请求头,优先用 fetch + keepalive 方案。
  • 提交的数据量尽量精简,避免因数据过大导致请求超时。
  • 不同浏览器在页面刷新、标签关闭时的行为略有差异,建议在实际场景中多做测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:33:19