如何合并含公共switchMap逻辑的两个Observable并获取双结果
当然可以合并啦!既然这两个 Observable 都依赖 selectedSite() 返回的 siteId,我们完全可以把它们整合到同一个数据流里,这样既能一次性拿到你需要的 routineFullInformation 和 measureFullInfo,还能避免重复订阅 selectedSite(),代码也会更简洁高效。
下面是修改后的完整代码,我会一步步给你解释:
this.subs.push( this.siteService.selectedSite().pipe( switchMap(({ id: siteId }) => { // 用 forkJoin 同时发起两个独立请求,等待两者都完成 return forkJoin([ // 保留原有的错误兜底逻辑 this.walkthroughService.getRoutineForSite(siteId).pipe( onErrorResumeNext(of(EMPTY_ROUTINE)) ), this.splunkService.getMeasures(siteId) ]); }), map(([routine, measureFullInfo]) => { // 保留原代码里对 this.routine 的赋值 this.routine = routine; // 转换 routine 为你需要的 routineFullInformation const routineFullInformation = WalkthroughService.routineToRoutineItemsPerRoomPerCategory(routine); // 返回包含两个结果的对象,方便后续 subscribe 使用 return { routineFullInformation, measureFullInfo }; }) ).subscribe(({ routineFullInformation, measureFullInfo }) => { // 处理 routineFullInformation 的原有逻辑 this.routineId = routineFullInformation.id; this.roomsMasterList = routineFullInformation.rooms; this.roomsMasterData = _.keyBy(routineFullInformation.rooms, 'id'); this.categoriesMasterList = routineFullInformation.categories; this.categoriesMasterData = _.keyBy(routineFullInformation.categories, 'id'); this.perRoomPerCategory = routineFullInformation.perRoomPerCategory; this.initializeForm(); // 处理 measureFullInfo 的逻辑 console.log(measureFullInfo); }) );
为什么这么改?
- 避免重复订阅:只订阅一次
selectedSite(),不会因为多次订阅导致重复触发流(比如site切换时只会发起一次请求组)。 - 并行请求提升效率:
forkJoin会同时发起两个请求,不用等第一个请求完成再发第二个,节省等待时间。 - 错误处理保留:原有的
onErrorResumeNext(of(EMPTY_ROUTINE))被保留,即使获取routine失败,也不会影响measure请求的执行,还能兜底返回空routine。 - 逻辑集中:所有相关逻辑都在同一个流里,后续维护起来更方便。
如果你的场景中两个请求有依赖关系(比如必须先拿到routine才能获取measures),那可以换成嵌套的 switchMap,但从你的代码来看,两个请求都是独立依赖siteId,所以 forkJoin 是最优的选择。
内容的提问来源于stack exchange,提问作者Dat Nguyen
相关产品推荐
相关产品推荐

