页面卸载时 fetch 请求会被浏览器强制终止,无法发送或响应;应改用 navigator.sendbeacon() 进行可靠上报,它不依赖 js 生命周期且不阻塞卸载。

因为页面卸载过程中,浏览器会中止所有尚未完成的网络请求,包括 fetch,即使你用 async/await 或 .then() 写了异步逻辑,也无法真正发出或收到响应。
浏览器主动终止网络活动
当用户触发页面跳转、刷新或关闭标签页时,beforeunload(或更现代的 pagehide)事件被触发,但此时浏览器已开始清理资源:
- JavaScript 执行可能被限制或快速中断(尤其在用户确认离开后)
- 所有待处理的
fetch请求会被强制取消,不会发送到服务端,也不会触发then或catch - 即使请求已发出,响应到达前页面已销毁,回调无法执行
fetch 不支持“即发即弃”的可靠上报
fetch 是基于 Promise 的异步操作,依赖事件循环和完整的生命周期。而卸载过程不等待 Promise 完成:
- 写
await fetch(...)在beforeunload里,代码看似执行了,但实际请求大概率被丢弃 - 没有机制让浏览器“等这个 fetch 结束再卸载”——这是设计上的故意限制,防止恶意页面阻塞退出
- 你可以用
navigator.sendBeacon()替代,它专为此场景设计:异步、无回调、不阻塞卸载
替代方案:用 sendBeacon 发送轻量数据
如果目标是上报用户行为(如停留时长、未保存草稿),应改用 sendBeacon():
- 它使用 HTTP POST 发送小段数据(通常 ≤64KB),且浏览器保证“尽力发送”,不依赖 JS 执行环境存活
- 无需等待响应,不返回 Promise,也不触发任何回调,适合卸载前最后上报
- 示例:
navigator.sendBeacon('/log', JSON.stringify({ action: 'leave', time: Date.now() }))
注意 beforeunload 的兼容性与限制
现代浏览器对 beforeunload 已大幅收紧:
- 仅允许弹出极简的原生提示(内容不可自定义),且只在用户有未保存输入等“可感知变更”时才生效
- 很多浏览器(如 Chrome 88+)已默认禁用该事件的提示功能,除非页面满足特定交互条件
- 推荐优先监听
pagehide或visibilitychange,它们更可靠、无干扰
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











