Angular中Server-Sent Event发起多次请求问题咨询
问题描述
我正在使用Angular和Spring Boot开发简易聊天系统,采用Server-Sent Event(SSE)实现。客户端已完成开发,可正常接收事件,但在浏览器网络控制台发现异常:预期仅调用一次接口,实际出现多次请求。添加onopen事件后确认该问题存在,请问这是我的实现错误还是Angular的正常行为?
以下是客户端代码:
private getMessages(): Observable<any> { return new Observable((observer: { next: (arg0: any) => void; }) => { let ess = new EventSource("http://localhost:8080/api/messages"); ess.onopen = ev => { console.log("Connection open") } ess.onmessage = ev => { this.zone.run(() => { observer.next(ev.data) }) } }) } ngOnInit(): void { this.sub = this.getMessages().subscribe({ next: (data: any) => { //console.log(data); this.addMessage(data) }, error: err => console.log(err) }); }
网络请求截图:
问题分析与解决
这不是Angular的正常行为,是你的SSE实现存在几个关键问题导致的重复连接:
缺少连接关闭逻辑
你的Observable没有处理订阅取消时的资源释放,当组件被销毁或者订阅被取消时,EventSource没有被关闭。如果组件因为路由跳转、变更检测等原因重新初始化,就会创建新的EventSource连接,旧连接可能还没断开,导致多次请求。解决办法:在Observable的清理函数里关闭
EventSource:private getMessages(): Observable<any> { return new Observable((observer: { next: (arg0: any) => void; }) => { const ess = new EventSource("http://localhost:8080/api/messages"); ess.onopen = ev => { console.log("Connection open") } ess.onmessage = ev => { this.zone.run(() => { observer.next(ev.data) }) } // 添加清理逻辑,订阅取消时关闭连接 return () => { ess.close(); console.log("Connection closed") }; }) }组件未正确销毁订阅
如果组件被多次实例化(比如路由复用、组件嵌套重复渲染),或者ngOnInit被多次触发,会重复创建订阅和SSE连接。需要在组件销毁时主动取消订阅:ngOnDestroy(): void { if (this.sub) { this.sub.unsubscribe(); } }SSE服务端连接异常导致自动重连
浏览器的EventSource默认会在连接断开后自动重连,如果你的Spring Boot服务端没有正确保持SSE长连接(比如超时、异常断开、响应头配置错误),浏览器就会自动发起新连接。检查服务端的响应头是否正确设置:Content-Type: text/event-streamCache-Control: no-cacheConnection: keep-alive
同时确保服务端不会主动关闭连接,维持长连接状态。
内容的提问来源于stack exchange,提问作者Giane
相关产品推荐
相关产品推荐

