单页应用中sse连接必须手动及时关闭,应在路由离开或组件卸载时调用close():react用useeffect清理函数,vue2用beforedestroy,vue3用onbeforeunmount;避免全局声明,按路由上下文精准关闭,并配合服务端感知释放资源。

单页应用中 SSE 连接必须手动、及时关闭,否则会持续占用连接、带宽和内存,甚至导致服务端无效推送。关键不是等浏览器自动清理,而是在路由离开或组件卸载时主动调用 close()。
在组件卸载时显式关闭 EventSource
SSE 连接不会随组件销毁自动释放,必须在生命周期钩子中手动关闭:
-
React:在
useEffect的清理函数里调用eventSource?.close() -
Vue 2:在
beforeDestroy钩子中执行this.eventSource?.close() -
Vue 3(Composition API):在
onBeforeUnmount中调用eventSource.close() - 避免将
EventSource声明在全局或模块顶层,防止跨路由复用却无法精准控制生命周期
按路由上下文精准关闭对应连接
多个页面可能同时开启不同 SSE 流(如通知流、订单流),仅调用 close() 不够,需确保关的是“当前页面该关的那个”:
- 为实例添加自定义标识,例如:
es.__routeContext = '/dashboard' - 在路由守卫(如
router.beforeEach)中遍历已存在的实例,对__routeContext匹配旧路径的执行.close() - 更稳妥方式是用
WeakMap管理路由与实例的映射,避免强引用阻碍垃圾回收
配合服务端做连接感知与资源释放
前端关闭后,若服务端不知情,仍可能向已失效连接推送数据:
- 关闭前可向服务端发送轻量终结请求(如
POST /api/sse/close?session=xxx),服务端据此清除会话缓存与推送任务 - 服务端监听响应对象的
close或底层 socket 的end事件,及时释放资源 - 为每个 SSE 请求附带
X-Route-Path等 header,服务端按当前活跃路由动态过滤推送内容
避免重复连接与重连风暴
路由快速切换易引发新建多个实例、旧实例未关闭的问题:
- 封装 SSE 工厂函数,内部用
Map缓存按路径/类型区分的实例,优先复用已有连接 - 设置重连节流:当
eventSource.readyState === 0(正在重连)时,延迟至少 2 秒再尝试,防止密集重连 - 监听
error事件后不要无条件立即重建,先判断是否因主动关闭触发(readyState为 0 且无网络错误)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











