如何合并两个Observable(含空Observable)并返回单一Observable
问题解决思路
首先纠正你代码里iif的用法错误:iif的第一个参数需要是返回布尔值的函数,否则会在初始化时就执行判断,而非订阅阶段。正确写法应该是:
const obs1 = iif(() => items1.length > 0, getObsList1, EMPTY); const obs2 = iif(() => items2.length > 0, getObsList2, EMPTY);
接下来针对你的需求,分两种场景给出解决方案:
场景1:合并两个流的所有发射值
如果希望结果流能发射obs1和obs2中的每一个Spatial值(不管哪个流有数据),直接用merge操作符即可,它会把两个同类型流合并成单一的Observable<Spatial>:
combinedObservables(items1: any[], items2: any[]): Observable<Spatial> { const obs1 = iif(() => items1.length > 0, getObsList1, EMPTY); const obs2 = iif(() => items2.length > 0, getObsList2, EMPTY); return merge(obs1, obs2); }
场景2:合并两个流的最新值(允许其中一个流为空)
如果需要等待两个流的最新值合并,但允许其中一个流为空(此时只取另一个流的值),可以用defaultIfEmpty处理空流,再通过map提取有效值:
import { combineLatest, iif, EMPTY, Observable } from 'rxjs'; import { defaultIfEmpty, map, filter } from 'rxjs/operators'; combinedObservables(items1: any[], items2: any[]): Observable<Spatial> { const obs1 = iif(() => items1.length > 0, getObsList1, EMPTY).pipe( defaultIfEmpty(undefined) ); const obs2 = iif(() => items2.length > 0, getObsList2, EMPTY).pipe( defaultIfEmpty(undefined) ); return combineLatest([obs1, obs2]).pipe( map(([val1, val2]) => val1 ?? val2), filter(val => val !== undefined) // 过滤两个流都为空的情况 ); }
为什么combineLatest不符合预期?
combineLatest的作用是当所有源流都至少发射过一次值后,每次任意一个源流发射新值,就将所有源流的最新值组合成数组发射,所以它的返回类型是Observable<[Spatial, Spatial]>(或包含undefined的联合类型),而非单一的Observable<Spatial>。而merge才是将多个同类型流的发射值合并成一个同类型流的操作符。
内容的提问来源于stack exchange,提问作者Lewis Patterson
相关产品推荐
相关产品推荐

