如何在浏览器关闭时更新数据库?求跨设备视频续播方案
解决浏览器关闭时保存视频播放进度的方案
你遇到的这个问题确实挺棘手的——同步Ajax被禁用后,onunload/beforeunload里的请求经常“掉链子”,只靠暂停按钮保存又覆盖不全场景。下面几个亲测靠谱的方案,既能解决浏览器关闭时的进度保存,还能实现跨设备续播:
1. 优先用 Beacon API(专门为卸载场景而生)
Beacon API是浏览器专门推出的接口,就是用来处理页面卸载时的异步数据发送的——它不会阻塞页面关闭流程,浏览器会兜底保证请求能发出去(只要网络正常),完美适配你的需求。
代码示例:
const video1 = document.getElementById('video1'); // 监听页面卸载前的事件 window.addEventListener('beforeunload', () => { const watchedTime = video1.currentTime; // 组装要发送的数据(支持FormData、Blob或字符串) const formData = new FormData(); formData.append('userId', '当前用户的唯一标识'); formData.append('videoId', '当前视频ID'); formData.append('watchedTime', watchedTime); // 发送Beacon请求 navigator.sendBeacon('/api/save-watched-progress', formData); });
注意:Beacon只支持POST请求,数据格式有一定限制,但存储播放进度这类简单数据完全够用。
2. 定时自动同步进度(双重保障)
除了卸载时的一次性保存,你可以每隔一段时间(比如30秒)自动把当前进度同步到后端。这样就算用户突然关闭浏览器,最多只会丢失几十秒的进度,用户体验影响极小,还能和暂停按钮的保存形成双重保险。
代码示例:
const video1 = document.getElementById('video1'); let syncTimer = null; // 视频开始播放时启动定时同步 video1.addEventListener('play', () => { syncTimer = setInterval(() => { const watchedTime = video1.currentTime; // 用普通异步fetch发送请求 fetch('/api/save-watched-progress', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ userId: '当前用户标识', videoId: '当前视频ID', watchedTime: watchedTime }) }); }, 30000); // 每30秒同步一次 }); // 暂停或结束播放时清除定时器,同时触发暂停保存 video1.addEventListener('pause', () => { clearInterval(syncTimer); // 执行你原来的暂停保存逻辑 const watchedTime = video1.currentTime; // 这里写暂停时的Ajax保存代码 });
3. 利用页面可见性变化事件(覆盖更多场景)
有时候用户不会主动暂停,只是切换标签页、最小化浏览器或者直接关窗口,这时候visibilitychange事件能精准捕捉到页面从“可见”变“隐藏”的瞬间,比beforeunload更可靠(有些浏览器会拦截beforeunload的请求或弹窗)。
代码示例:
const video1 = document.getElementById('video1'); document.addEventListener('visibilitychange', () => { if (document.hidden) { // 页面隐藏时立即保存进度 const watchedTime = video1.currentTime; // 这里可以用Beacon或者普通异步请求发送 navigator.sendBeacon('/api/save-watched-progress', new FormData().append('watchedTime', watchedTime)); } });
关于跨设备续播的补充
要实现跨设备续播,核心是把播放进度和用户账号绑定,存储到后端数据库。上面的方案都是把进度同步到后端,用户下次登录时,先从数据库拉取该用户对应视频的最近播放进度,再设置视频的currentTime即可。
另外,你可以结合localStorage做本地缓存优化:
- 每次播放时,优先读取localStorage的进度(避免网络请求延迟)
- 同时请求后端获取最新进度,若后端进度更新,则覆盖本地缓存
- 每次同步到后端后,也更新localStorage的值
这样既保证了跨设备的进度一致性,又有本地缓存的流畅体验。
内容的提问来源于stack exchange,提问作者Arman Jelodar
相关产品推荐
相关产品推荐

