Fetch keepalive 请求有什么大小和生命周期边界
页面跳转或关闭前,前端经常还想补发一次埋点、会话状态或轻量日志。fetch(url, { keepalive: true }) 可以让请求在发起它的页面卸载后继续发送,但它不是“永不超时”的通道,也不是把 HTTP 连接永久挂住。真正需要记住的有两条:请求体要按字节控制,多个尚未完成的 keepalive 请求会共同消耗有限额度;页面消失后只能提高送达机会,不能保证服务器一定完成业务处理。
官方资料:https://developer.mozilla.org/en-US/docs/Web/API/RequestInit https://fetch.spec.whatwg.org/
- Fetch 的 keepalive 与 HTTP 的 Keep-Alive 不是一回事,前者解决的是页面卸载时的请求生命周期。
- 实战上把单次事件控制在 60 KiB 以内更稳妥;规范检查的是同一 fetch group 中未完成 keepalive 请求体的累计量,硬边界是 64 KiB。
- 它适合分析事件、离开记录等可容忍丢失的轻量数据;订单提交、扣款和关键状态变更仍应走正常可靠接口。
Fetch keepalive 与 HTTP Keep-Alive 解决的不是同一个问题
前端代码里的 keepalive: true 是 Fetch API 的请求选项。它的目标是:文档开始卸载后,用户代理不要因为原页面环境即将消失就立刻放弃这次请求。HTTP 头里的 Keep-Alive 则属于连接管理语义,讨论的是连接空闲多久、最多承载多少请求;不要把两个同名词混成一个开关。
因此,下面的场景适合考虑 keepalive:用户点击离开前上报一次阅读进度、记录一次导航来源、发送小型诊断事件。它不适合承载大文件、长轮询、需要持续响应的交互,也不应成为关键写入唯一的成功凭据。
Fetch keepalive 的 64 KiB 不是单请求孤立额度

MDN 给出的工程记忆点是 keepalive 请求体限制为 64 KiB。Fetch 标准的算法更精确:当请求有可计算的 Content-Length 时,浏览器会把本次请求体长度与同一 fetch group 中仍未完成的 keepalive 请求体长度相加;总和超过 64 KiB,就返回 network error。也就是说,连续快速发出多个小请求,也可能因为累计超界而失败。
这里的 64 KiB 约束讨论的是请求体,不是响应体大小,也不是“每个请求都独享 64 KiB”。JSON 还要按 UTF-8 字节计算,中文字符不能简单按 JavaScript 的字符串长度估算。生产实现通常给自己留出余量,例如把单个事件控制在 60 KiB 以下,并避免在离开瞬间并发堆积多条 keepalive 请求。
页面离开时它能保活什么、不能保证什么

触发点可以放在应用已经决定离开的时刻,或使用 pagehide 做最后一次轻量上报。示例先计算 UTF-8 字节数,再调用 keepalive;60 * 1024 是人为保留的工程余量,不是把规范上限改成了 60 KiB。
function sendExitEvent(detail) {
// JSON 字符串的字符数不等于 UTF-8 字节数,先按真实字节计量。
const body = JSON.stringify({ type: "page_exit", detail });
const bodyBytes = new TextEncoder().encode(body).byteLength;
// 给同一页面中其他未完成的 keepalive 请求留出余量。
if (bodyBytes > 60 * 1024) return;
// 不等待响应;页面离开后 Promise 可能再也没有可见的消费方。
void fetch("/telemetry/exit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body,
keepalive: true
}).catch(() => {
// 离开场景允许丢失,避免未处理的 rejected Promise 干扰页面日志。
});
}
window.addEventListener("pagehide", () => {
// 事件应可重复接收,服务端用 eventId 或幂等键去重。
sendExitEvent({ eventId: crypto.randomUUID() });
});
这个写法只提高了请求在页面卸载后继续传输的机会。设备断网、浏览器进程被系统回收、请求被策略拦截、服务端超时或返回错误时,数据仍可能丢失;浏览器也不会替你把一次分析事件变成事务。服务端要把这类接口设计成幂等、快速响应,并接受重复或缺失。
按数据重要性选择 keepalive、sendBeacon 或正常接口
| 场景 | 更合适的选择 | 判断理由 |
|---|---|---|
| 小型离开事件,需要自定义方法或读取响应 | fetch + keepalive:true | 保留 Fetch 的请求配置和 Promise,但仍要接受尽力而为。 |
| 只想在页面离开时发送少量分析数据 | navigator.sendBeacon() | 接口语义更直接,调用方通常不需要处理响应。 |
| 订单、支付、权限、库存等关键状态 | 正常接口 + 服务端幂等与重试 | 不能把页面卸载后的 best effort 当成业务成功凭据。 |
还有一个常见误区:把 keepalive 写上,就以为跨域、凭据、CORS 和服务端处理都自动变得可靠。它只改变请求生命周期的一部分,仍要遵守 Fetch 的模式、凭据策略和服务器端接口约束。若事件很重要,下一次打开页面时补偿上报通常比在卸载回调里不断加大请求体更可控。
相关问题
64 KiB 是请求体还是响应体?
这里的 keepalive 配额主要针对请求体及其未完成累计量,不是响应体下载上限。不要用它发送大批量日志,也不要据此推断响应一定能读完。
把 JSON 压缩后就一定能发送吗?
不一定。压缩后的传输方式、实际请求体、并发中的其他 keepalive 请求和浏览器策略都可能影响结果。应用层仍应按字节设上限,并在服务端保留幂等处理。
为什么不用 unload 事件等待 fetch 完成?
卸载阶段不适合等待异步响应。keepalive 的价值正是让请求脱离页面销毁节奏继续尽力发送;若业务必须确认成功,应在页面仍然可交互时完成正常请求。
IndexedDB onupgradeneeded 怎样迁移对象仓库
- 上一篇
- IndexedDB onupgradeneeded 怎样迁移对象仓库
- 下一篇
- IndexedDB 游标方向怎样影响遍历顺序
-
- 文章 · 前端 | 20分钟前 | key 前端路由 Navigation API currentEntry NavigationHistoryEntry currententrychange
- Navigation API currentEntry 怎样读取当前导航状态
- 348浏览 收藏
-
- 文章 · 前端 | 26分钟前 |
- IndexedDB 游标方向怎样影响遍历顺序
- 253浏览 收藏
-
- 文章 · 前端 | 29分钟前 | 数据库迁移 IndexedDB 对象仓库 versionchange onupgradeneeded
- IndexedDB onupgradeneeded 怎样迁移对象仓库
- 321浏览 收藏
-
- 文章 · 前端 | 31分钟前 | javascript · 前端开发 · 浏览器API · localStorage sessionStorage storage事件 Web Storage 同源文档
- Web storage 事件为什么只通知其他文档
- 200浏览 收藏
-
- 文章 · 前端 | 34分钟前 |
- Web TransformStream 怎样体现背压
- 424浏览 收藏
-
- 文章 · 前端 | 37分钟前 | 前端 · javascript · Web API Fetch AbortController AbortSignal abort(reason) signal.reason
- Web AbortController.abort 怎样保留取消原因
- 318浏览 收藏
-
- 文章 · 前端 | 38分钟前 | Fetch AbortController ReadableStream cancel releaseLock
- Web ReadableStream 怎样取消未读响应
- 491浏览 收藏
-
- 文章 · 前端 | 18小时前 |
- IndexedDB 事务自动提交前怎样完成异步读取
- 208浏览 收藏
-
- 文章 · 前端 | 18小时前 | CSS flex Grid 可访问性 键盘导航 reading-order reading-flow
- CSS reading-flow 怎样让卡片的键盘顺序跟随视觉布局
- 308浏览 收藏
-
- 文章 · 前端 | 18小时前 | CSS textarea min-height field-sizing
- CSS field-sizing content 与 min-height 怎么配合
- 282浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 1029次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 1030次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 1173次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 1134次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 976次使用
-
- Chrome DevTools 如何验证页面能否命中 bfcache:Run Test 与失败原因定位
- 2026-09-04 259浏览
-
- Chrome DevTools 模拟慢网络验证前端加载的操作步骤
- 2026-10-17 118浏览
-
- Chrome 152 移除 Private Aggregation API:网站开发者先查哪些隐私接口影响
- 2026-08-26 242浏览
-
- GitHub 如何重建超大型拉取请求的差异渲染
- 2026-10-05 446浏览
-
- 前端搜索竞态治理实战:用 AbortController 取消过期请求
- 2026-06-12 178浏览

