eventsource自动携带last-event-id的前提是:服务端事件必须包含合法id字段且以data:开头、双换行分隔;浏览器仅在满足这两条件时才记录并重连时自动发送该头。

EventSource 自动携带 Last-Event-ID 的前提条件
浏览器只有在满足两个硬性条件时,才会在重连请求头中自动带上 Last-Event-ID:
- 上一个连接中,服务器发送的事件必须包含
id字段(如id: 123\n) - 事件内容必须以
data:开头,且格式合法(每条消息以双换行分隔)
如果服务端返回的是纯 JSON 字符串(比如 {"msg":"hello"})而没加 data: 前缀,或者漏了 id 行,EventSource 就不会记录最后 ID,重连时自然也不会发送该头。
前端手动管理 lastEventId 的典型误操作
很多人试图用 eventSource.lastEventId 在断开前主动保存 ID,再在重建连接时传参——这是无效的。EventSource 构造函数不接受 lastEventId 参数,也不能通过属性设置它。
正确做法只有一种:让浏览器自己记、自己发。
所以你要做的是:
- 确保每次
onmessage或addEventListener('message')触发时,事件对象的event.lastEventId是可用的(它由浏览器从响应头解析而来) - 不要覆盖或清空
eventSource实例,否则历史 ID 丢失 - 如果必须重建连接(比如切换用户),应先调用
eventSource.close(),再用新 URL 创建实例(旧 ID 不会跨 URL 复用)
后端必须配合的三个关键点
Last-Event-ID 是个“请求头”,不是客户端能伪造的凭证,它的价值完全取决于服务端是否真按它恢复流。常见疏漏包括:
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- 忽略请求头解析,直接从头推数据(导致重复)
- 把
Last-Event-ID当字符串处理,但服务端生成的id是数字(如id: 42),造成类型不匹配跳过逻辑 - 没做边界检查:若客户端传
Last-Event-ID: 9999,但服务端只存了 100 条记录,需返回 416 或跳过,而非崩溃
FastAPI 示例中必须显式读取并转换:
last_event_id: str | None = Header(None, alias="Last-Event-ID")然后转成整数再计算起始偏移,不能直接用字符串比较。
调试时怎么确认 Last-Event-ID 是否生效
别只看控制台日志,得抓包验证:
- 打开浏览器 DevTools → Network → 找到 SSE 请求 → 查看 Headers 标签页下的
Request Headers区域,确认存在Last-Event-ID: xxx - 同时检查响应体里每条消息是否含
id: N\n和data: ...\n\n结构 - 如果重连请求里没有这个头,说明前一次连接根本没收到带
id的合法事件;如果有头但数据还是从头开始,问题一定出在服务端逻辑未消费该头
这种链路里,任何一环断掉,续传就失效——而且错误表现是“看起来正常”,只是数据重复或跳变,极难定位。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










