使用RxJS fromEvent连接命名SSE,如何捕获连接失败错误?
问题
我正在使用RxJS的fromEvent连接命名SSE事件,希望捕获连接丢失时的错误。以下是我的代码:
namedEvent() { try { const eventSource = new EventSource( 'adress' ); return fromEvent(eventSource, 'eventName').pipe( catchError((err) => { // handle the error console.log('Error:', err); return of(null); // return an empty observable to prevent the stream from completing }) ); } catch (err) { // handle the error console.log('Error:', err); return of(null); // return an empty observable to prevent the stream from completing } }
我在连接初始化时使用try/catch块捕获错误,在Observable中使用RxJS的catchError捕获流错误,但当前代码没有任何错误输出,浏览器仅抛出net::ERR_NAME_NOT_RESOLVED错误,网络标签页显示“failed to load response data”。请问该如何捕获这类错误?
解决方案
你当前写法捕获不到错误的核心原因:
try/catch只能捕获同步异常,而EventSource的连接错误是异步触发的,初始化阶段不会立即抛出异常;fromEvent(eventSource, 'eventName')仅监听了自定义命名事件,没监听EventSource原生的error事件,且catchError只能捕获当前Observable流内的错误,SSE连接错误不会流入这个事件流。
下面提供两种可行的实现方式:
方式一:合并事件流与错误流统一处理
将命名事件流和错误流合并,用RxJS操作符统一捕获错误:
import { fromEvent, merge, of } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; namedEvent() { const eventSource = new EventSource('address'); // 监听自定义命名事件 const eventStream = fromEvent(eventSource, 'eventName'); // 监听error事件,将错误转为Observable的错误通知 const errorStream = fromEvent(eventSource, 'error').pipe( map(() => { throw new Error('SSE连接失败或已断开'); }) ); // 合并两个流,统一处理错误 return merge(eventStream, errorStream).pipe( catchError((err) => { console.log('Error:', err.message); // 关闭连接避免内存泄漏 eventSource.close(); return of(null); }) ); }
方式二:直接绑定EventSource错误回调
不通过RxJS流处理,直接给EventSource绑定onerror回调:
import { fromEvent, of } from 'rxjs'; import { catchError } from 'rxjs/operators'; namedEvent() { const eventSource = new EventSource('address'); // 单独处理SSE连接错误 eventSource.onerror = (event) => { console.log('SSE连接错误:', event); eventSource.close(); // 这里可添加重连、告警等逻辑 }; return fromEvent(eventSource, 'eventName').pipe( catchError((err) => { console.log('事件流内部错误:', err); eventSource.close(); return of(null); }) ); }
额外注意事项
- 错误发生后务必调用
eventSource.close()关闭连接,避免无效重连和内存泄漏; - 若需要自动重连,可在错误回调中延迟重新创建EventSource实例;
net::ERR_NAME_NOT_RESOLVED这类网络错误会触发EventSource的error事件,上述两种方式都能正常捕获。
内容的提问来源于stack exchange,提问作者Sator
相关产品推荐
相关产品推荐

