合并两个Observable:过滤obs1首个null值与obs2所有null值
解决方法
你需要实现两个过滤规则:
- 所有
obs2为null的情况都要过滤掉 - 仅排除
obs1首次输出为null的场景,后续obs1输出的null正常保留
RxJS没有专门用来只过滤首个值的操作符,但可以通过带索引的操作符组合实现,下面是两种简洁的写法:
写法1:先预处理obs1$,再组合流
先单独处理obs1$,过滤掉它首次输出的null,再和obs2$做combineLatest:
import { combineLatest } from 'rxjs'; import { filter, map } from 'rxjs/operators'; combineLatest([ this.obs1$.pipe( // 给每个值加上索引标记 map((val, idx) => ({ val, idx })), // 只排除索引为0且值为null的项 filter(({ val, idx }) => !(idx === 0 && val === null)), // 还原回原始值 map(({ val }) => val) ), this.obs2$ ]).pipe( // 全局过滤obs2为null的情况 filter(([, obs2]) => obs2 != null) ).subscribe(([obs1, obs2]) => { // 执行你的逻辑 });
写法2:在组合后的流中统一处理
如果想把所有逻辑放在combineLatest之后的pipe里,可以用scan跟踪是否已经处理过obs1的首次输出:
import { combineLatest } from 'rxjs'; import { filter, scan, map } from 'rxjs/operators'; combineLatest([this.obs1$, this.obs2$]).pipe( // 用scan记录状态:是否已经跳过了obs1的首次null scan((state, currentVals) => { const [obs1] = currentVals; return { vals: currentVals, firstObs1Handled: state.firstObs1Handled || !(obs1 === null && !state.firstObs1Handled) }; }, { firstObs1Handled: false }), // 过滤条件:obs2不为null,且要么已经处理过首次obs1,要么首次obs1不是null filter(({ vals: [, obs2], firstObs1Handled }) => { return obs2 != null && (firstObs1Handled || vals[0] !== null); }), // 还原回原始值数组 map(({ vals }) => vals) ).subscribe(([obs1, obs2]) => { // 执行你的逻辑 });
小提示
第一种写法可读性更强,因为把obs1的过滤逻辑和obs2的全局过滤逻辑分开了,推荐优先用这种。
内容的提问来源于stack exchange,提问作者inquisitivemongoose
相关产品推荐
相关产品推荐

