SSE连接失败时不会触发onerror而静默停留在readyState===0,需主动检测:创建后5秒内未变为1则视为失败,配合fetch预检、URL传参鉴权、分层错误提示及及时关闭实例防泄漏。

连接建立失败时,SSE 不会触发 onerror,而是直接停留在 readyState === 0(EventSource.CONNECTING 状态),且不会自动重试——这正是最容易被忽略的“静默失败”场景。必须主动检测并干预。
监听 loadstart + error 双事件组合判断初始连接状态
仅靠 onerror 无法覆盖连接未发起就失败的情况(如 DNS 解析失败、CORS 拒绝、401/403 响应)。需结合 XMLHttpRequest 或 fetch 预检,或更实用的做法是:在创建 EventSource 后立即检查 readyState 并设置超时兜底:
- 创建实例后,若
eventSource.readyState === 0且 5 秒内未变为 1(OPEN),视为初始连接失败 - 此时
onerror很可能从未触发(尤其 CORS 或 4xx 错误),需手动执行错误处理逻辑 - 推荐封装一个
waitForOpen(timeout = 5000)工具函数,内部用setTimeout+clearTimeout监控状态变化
捕获服务端非 2xx 响应(如 401、403、502)
当服务器返回非 2xx HTTP 状态码时,EventSource 会立即关闭连接,readyState 变为 0,但 onerror 的 event 对象不携带响应码——浏览器不暴露该信息。应对方式:
基于三引擎设计,从微信文章、新闻和博客网页提取干净内容,支持标题作者日期元数据,多格式和批量处理。
- 服务端应在非 2xx 响应体中返回简明错误描述(如
{"error":"Unauthorized"}),前端通过fetch预请求 /health 或 /sse-endpoint 进行鉴权校验 - 若 SSE 接口需 token,建议在 URL 中拼接参数(如
/sse?token=xxx),避免因 header 不被 EventSource 支持而引发 401 静默失败 - 对已知需登录态的场景,连接前先调用
fetch('/api/auth/status'),失败则跳过 SSE 初始化
区分网络不可达与服务端拒绝
初始连接阶段的失败原因需分层提示,提升用户感知:
立即学习“Java免费学习笔记(深入)”;
- navigator.onLine === false:直接显示“⚠️ 当前无网络连接,请检查 Wi-Fi 或移动数据”
- 预检 fetch 失败且 status >= 500:提示“❌ 服务器暂时不可用,请稍后再试”
- 预检返回 401/403:引导用户重新登录或检查权限
- 超时 + readyState 仍为 0:归类为“⚠️ 无法连接到实时服务,请确认地址是否正确”
避免重复初始化和内存泄漏
连接建立失败后若未清理,多次重试会累积多个未激活的 EventSource 实例:
- 每次新建前,先调用
eventSource?.close()并置为null - 使用 WeakMap 或闭包变量跟踪当前实例,防止全局变量残留
- 在组件卸载(如 Vue
onBeforeUnmount、ReactuseEffect cleanup)时强制关闭并重置状态

















