eventsource默认自动重连,但需服务端在事件流中显式发送retry:字段(如retry: 5000)才能生效;否则浏览器采用不可控的退避策略,且监听error后调用close()或赋值null会终止重连。

EventSource 默认就重连,但重连行为不按预期?
EventSource 本身具备自动重连能力,不是“需要手动实现”的功能。它会在连接关闭(如服务端返回非 200、网络中断、响应流结束)后,等待 retry 指定毫秒数再发起新请求。问题往往出在:服务端没发 retry: 字段、客户端没监听 error 事件、或误以为断开后要自己调 new EventSource()。
- 浏览器默认重试间隔是 3 秒(即
retry: 3000),但仅当服务端响应头或事件流中明确设置了retry:才生效;否则可能回退为浏览器自定策略(Chrome 实际可能用指数退避) - 只要
EventSource实例未被销毁(比如没赋值为null或脱离作用域),它就会持续尝试重连——不需要你在error里重新new EventSource() - 如果服务端响应状态码不是 200(如 503、401),EventSource 会立即触发
error,然后等待retry时间后重试;若响应 200 但流提前关闭(如 Node.js 中res.end()),也会触发重连
如何让 retry 值真正生效?
关键在服务端响应流中写入 retry: 行。仅靠响应头 Access-Control-Allow-Origin 或 Content-Type: text/event-stream 不够,retry 必须出现在事件流正文中,且必须在第一个事件前或每个事件块内。
retry: 5000 data: hello id: 1 data: world
-
retry:后面只能跟纯数字(单位毫秒),不能带空格或单位,例如retry: 5s无效 - 该指令只对后续事件生效;如果放在事件块中间,只影响之后的重试间隔
- 前端无法通过 JS 修改已创建实例的
retry值——它是只读属性,修改eventSource.onopen或eventSource.readyState都不影响重连逻辑
为什么监听 error 事件后还收不到重连?
常见误区是把 error 当作“连接失败终点”,立刻 eventSource.close() 或 eventSource = null,这直接终止了内置重连机制。
-
error事件会在连接关闭、网络异常、CORS 失败等场景触发,但它**不表示重连已终止**——只要实例还活着,重连就会继续 - 不要在
error回调里调eventSource.close(),除非你确定要放弃;更不要重复 new 实例,否则旧实例可能还在后台重试,造成请求堆积 - 可通过检查
eventSource.readyState判断当前状态:0(closed)、1(opening)、2(open);重连过程中它会反复经历0 → 1 → 2 - 调试时可在
error中打印eventSource.url和eventSource.readyState,确认是否真被销毁
服务端没发 retry 时,浏览器实际怎么重连?
没有 retry: 指令时,各浏览器行为不一致,且不会严格遵循“3 秒”。Chrome 会使用类似指数退避的策略(首次约 1s,随后 2s、4s、8s…),Safari 更激进,Firefox 相对保守。这意味着:不显式控制 retry,你就无法预测重连节奏。
- Node.js 示例中,漏掉
res.write('retry: 3000\n')就会导致重连间隔不可控 - Nginx 反向代理下,若配置了
proxy_buffering off但没设chunked_transfer_encoding on,可能导致流被截断,触发频繁重连 - 如果服务端用
keep-alive但超时设得太短(如 5 秒),连接会被主动断开,EventSource 误判为服务端异常而重连——此时应调大后端 keep-alive timeout
retry 值和后端超时设置必须对齐;否则你会看到“刚连上就断”“重连越来越慢”这类现象,根源不在前端代码,而在流协议细节没对齐。前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











