NgRx Effect仅触发一次,多无人机SSE连接事件分发异常求助
解决Angular Effect中处理多个SSE连接的问题
你这情况正好踩中了concatMap和switchMap的典型局限性:前者会顺序等待前一个流完成才处理下一个,但你的SSE连接是长期存活的(不会主动完成),导致后面的action全被堵在了队列里;后者会直接取消之前的订阅,只保留最新的请求,所以只能看到最后一个drone的输出。
你需要的是mergeMap(和flatMap是同一个操作符的别名),它会为每个输入的action创建完全独立的订阅,所有流并行处理、互不干扰,完美匹配你“逐个订阅并独立处理每个事件”的需求。
修改你的Effect代码,把concatMap换成mergeMap即可:
@Effect() startStatusUpdate$ = this.actions$.pipe( ofType<featureActions.OpenUsedDroneUpdateStatusChannelRequest>(featureActions.ActionTypes.OpenUsedDroneUpdateStatusChannelRequest), // 替换concatMap为mergeMap mergeMap((action) => this.droneDataService.openUsedDroneUpdateStatusChannel(action.payload).pipe( map(result => { console.log('there', action.payload.droneId); // 记得返回对应的Action,否则Effect无法触发状态更新 return new featureActions.OpenUsedDroneUpdateStatusChannelSuccess(result); }), catchError((error: HttpErrorResponse) => { // 错误处理要返回Action或EMPTY,避免Effect因错误中断 return of(new featureActions.OpenUsedDroneUpdateStatusChannelFailure(error)); }), ) ) );
额外提醒:
- mergeMap的核心特性:它不会等待前一个Observable完成,只要新action进来就立刻创建新订阅,所有订阅并行运行。对于SSE这种长期存活的流来说,刚好能实现每架无人机的连接独立存在、各自接收推送消息。
- 错误处理的细节:原代码里
catchError返回空值会导致Effect遇到第一个错误就停止工作,一定要返回一个错误Action或者EMPTY来维持Effect的活跃性。 - 内存泄漏防范:如果需要在特定时机(比如组件销毁、用户退出)关闭这些SSE连接,可以在
openUsedDroneUpdateStatusChannel返回的流后添加takeUntil操作符,监听销毁信号来取消订阅。
内容的提问来源于stack exchange,提问作者Crocsx
相关产品推荐
相关产品推荐

