
使用 fetch 的 keepalive 选项可在 beforeunload 事件中异步发送请求,确保请求在页面关闭后仍能完成,且不触发浏览器的“离开此页面?”确认弹窗。
使用 `fetch` 的 `keepalive` 选项可在 `beforeunload` 事件中异步发送请求,确保请求在页面关闭后仍能完成,且不触发浏览器的“离开此页面?”确认弹窗。
在 Web 开发中,常需在用户离开页面前执行清理操作(如结束会话、上报行为日志或保存草稿)。但直接在 window.onbeforeunload 中调用 fetch() 会导致请求被立即终止——因为标准 fetch 是“可中断”的,而页面卸载会中止所有活跃的网络请求。
幸运的是,Fetch API 提供了 keepalive 选项,专为此类场景设计:它允许请求在页面卸载后继续在后台发送,并保证其在网络栈中被优先处理,无需等待 Promise 解析,也不会触发任何用户可见的提示框。
以下是推荐的实现方式:
window.addEventListener('beforeunload', (event) => {
// 发起带 keepalive 的请求(注意:key 是 keepalive,不是 keepAlive)
fetch('/api/endSession', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ reason: 'page_unload' }),
keepalive: true // ✅ 关键:启用后台持久传输
});
// 注意:不要 return 非空字符串(否则会强制触发确认弹窗)
// 也不要 await 或返回 Promise —— keepalive 请求必须是 fire-and-forget
});⚠️ 重要注意事项:
- keepalive: true 是唯一安全、合规的解决方案;async/await、setTimeout 或 navigator.sendBeacon()(虽可用但限制更多)均非本场景最优选;
- keepalive 仅支持 GET 和 POST 方法,且请求体大小通常受限(Chrome 约 64KB),超限将静默失败;
- 不要在 beforeunload 中 return 字符串(如 return '请保存数据'),否则会激活浏览器默认提示,违背“无弹窗”需求;
- 服务端应具备幂等性设计,因 keepalive 请求可能在网络不稳定时重复送达(尽管概率低);
- 兼容性良好:Chrome 51+、Firefox 53+、Edge 79+、Safari 11.1+ 均已支持(caniuse.com)。
✅ 总结:当需要静默、可靠地在页面卸载前提交关键请求时,fetch(..., { keepalive: true }) 是现代浏览器的标准答案——简洁、高效、无干扰。










