onerror 是 eventsource 的错误信号接口而非万能中断开关,仅在 tcp 断开、非2xx响应、缺失响应头或数据格式严重错误时触发,不响应心跳超时、wkwebview静默失效或页面休眠;需禁用原生重连,结合指数退避、网络检测与 last-event-id 实现可控重连和断点续传。

onerror 触发的真实含义
它会在以下情况被调用:
• TCP 连接断开(如网络闪断、Wi-Fi 切换)
• 服务端返回非 2xx 状态码(401/404/500 等)
• 响应头缺失 Content-Type: text/event-stream
• 流数据格式严重错误(如连续多个空行后无 data: 字段)
⚠️ 注意:它**不会**在以下情况触发:
• 服务端心跳超时但连接仍存活(如 Nginx 默认 60s 关闭空闲连接,此时 readyState 可能卡在 0,但 onerror 不响)
• iOS WKWebView 中连接静默失效(尤其旧版本)
• 客户端页面后台休眠导致事件循环暂停
原生自动重连的三大硬伤
浏览器默认会尝试重连,但逻辑极简:
• 仅对网络层失败有效;遇到 4xx/5xx 直接终止,不再重试
• 重连间隔由服务端 retry: 响应头决定(如 retry: 5000),客户端无法干预
• 没有退避策略:失败 10 次,每次都是等固定秒数,白耗资源
用 onerror 做真正可控的重连起点
正确做法是:禁用原生重连 + 在 onerror 中启动自定义流程:
• 创建 EventSource 时不依赖 retry 头:new EventSource(url, { withCredentials: true })
• 监听 onerror 后立即 close 当前实例(避免残留)
• 启动指数退避定时器,带随机抖动防雪崩
• 记录重连次数,超限后主动放弃或提示用户
• 每次重连前检查网络状态(navigator.onLine)和 readyState
断点续传不能只靠 onerror
onerror 只管“连不上”,不管“丢没丢数据”。要避免消息重复或遗漏,必须配合:
• 客户端在每条 message 处理成功后,立刻更新本地 last-event-id(存 localStorage + 内存)
• 重连请求时,通过 headers['X-Last-Event-ID'] 或 URL 参数带上该 ID
• 服务端据此从对应位置继续推送,而非从头开始
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











