eventsource 必须用 new eventsource() 初始化,url 需同源或配 cors;跨域缺 access-control-allow-origin 会导致静默失败、onerror 反复触发、readystate 停在 0;常见错误包括漏 new、相对路径误用、未手动编码 query 参数;需立即检查 readystate 并正确绑定 message 或自定义事件监听器;服务端格式错误(如 data: 后少换行)会丢弃整条消息;浏览器内置重连不可控,应手动管理连接并防抖重建;务必在页面卸载前调用 close() 并用 removeeventlistener 清理监听器;服务端流中断后事件丢失需业务层兜底。

EventSource 构造函数的正确初始化方式
必须用 new EventSource() 实例化,且传入的 URL 必须是同源或已配好 CORS 的服务端地址。跨域时服务端响应头里缺 Access-Control-Allow-Origin 会导致连接静默失败——浏览器不会报错,但 onerror 会被反复触发,readyState 停在 0。
常见错误写法:EventSource("url")(漏掉 new)或传入相对路径却没注意当前页面 base URL 影响。
- URL 应为完整路径或以
/开头的绝对路径,避免依赖当前页面路径解析 - 不支持 query 参数自动编码,需手动
encodeURIComponent特殊字符 - 构造后立即检查
eventSource.readyState:0 表示未连接,1 是正在连接,2 是已打开
监听 message 事件与自定义事件的区别
message 是默认事件名,对应服务端未指定 event: 的消息;而自定义事件(如 event: update)需用 addEventListener("update", handler) 显式绑定,不能靠 onmessage 捕获。
服务端发的每条消息以空行分隔,格式错误(比如 data: 后少换行)会导致整条被丢弃,且不会触发 onerror。
-
onmessage只收默认事件,addEventListener("message", ...)效果相同 - 自定义事件名区分大小写,服务端写
event: UPDATE,前端就得监听"UPDATE" -
event:和data:行必须顶格,前面不能有空格,否则被忽略
连接异常时的重连控制逻辑
浏览器对 EventSource 有内置重试机制:断开后默认等待约 3 秒重连,失败则指数退避(最多到几分钟)。但这个行为不可控,且无法感知“重连中”状态。
真正可靠的方案是手动管理连接:监听 onerror,判断 readyState 是否为 0,再调用 close() 后新建实例。不手动关闭旧实例会导致内存泄漏和重复监听。
-
onerror触发时,先检查eventSource.readyState === 0再决定是否重建 - 不要在
onerror里直接new EventSource(),应加防抖或延迟,避免雪崩重连 - 服务端可通过
retry:字段建议重连间隔(单位毫秒),但仅作提示,浏览器不一定遵守
关闭连接与资源清理的关键点
页面卸载前不调用 eventSource.close(),连接会持续占用 socket,Chrome 中可能表现为 DevTools Network 面板里一直显示 pending 请求,甚至影响后续页面加载。
另外,addEventListener 绑定的回调不会随 close() 自动解绑,如果组件多次挂载/卸载(如 React 中),旧监听器仍驻留内存。
- 务必在组件销毁、
beforeunload或visibilitychange为 hidden 时调用close() - 用
removeEventListener清理监听器,注意函数引用必须一致(不能用匿名函数) - 服务端流结束时发
event: close\ndata:\n\n并关闭 response,前端onerror仍会触发一次,属正常行为
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











