RxJS技术实现:仅当另一个Observable为假时触发订阅输出
解决方案
基础场景:仅当另一个Observable为false时触发输出
通过 withLatestFrom 结合 filter 即可实现,先获取最新加载状态,再过滤掉加载中的值:
import { withLatestFrom, filter, map } from 'rxjs/operators'; import { BehaviorSubject } from 'rxjs'; const loadingSubject$ = new BehaviorSubject<boolean>(false); const valueSubject$ = new BehaviorSubject<string>(''); valueSubject$ .pipe( // 获取最新的loading状态 withLatestFrom(loadingSubject$), // 仅保留loading为false的情况 filter(([_, isLoading]) => !isLoading), // 提取原始value map(([value]) => value) ) .subscribe(value => { console.log(value); }); valueSubject$.next('1') // 输出 '1' valueSubject$.next('2') // 输出 '2' loadingSubject$.next(true); valueSubject$.next('3') // 无输出 valueSubject$.next('4') // 无输出 loadingSubject$.next(false); valueSubject$.next('5') // 输出 '5'
复杂场景:加载状态变为false后需等待指定时长才允许输出
需要在加载状态切换为false后,延迟一段时间再开放输出权限。通过嵌套 switchMap 控制权限状态,结合 withLatestFrom 过滤值:
import { withLatestFrom, filter, map, switchMap, distinctUntilChanged } from 'rxjs/operators'; import { BehaviorSubject, of, timer } from 'rxjs'; const loadingSubject$ = new BehaviorSubject<boolean>(false); const valueSubject$ = new BehaviorSubject<string>(''); valueSubject$ .pipe( // 结合动态的输出权限状态 withLatestFrom( loadingSubject$.pipe( switchMap(isLoading => { if (isLoading) { // 加载中直接禁止输出 return of(false); } // 加载结束后,先禁止输出,100ms后开放 return timer(100).pipe(mapTo(true), startWith(false)); }), distinctUntilChanged() ) ), // 仅保留允许输出的情况 filter(([_, isAllowed]) => isAllowed), // 提取原始value map(([value]) => value) ) .subscribe(value => { console.log(value); }); valueSubject$.next('1') // 输出 '1' valueSubject$.next('2') // 输出 '2' loadingSubject$.next(true); valueSubject$.next('3') // 无输出 loadingSubject$.next(false); valueSubject$.next('4') // 无输出 setTimeout(() => { valueSubject$.next('5') // 输出 '5' }, 101);
逻辑说明
- 内部
switchMap根据加载状态生成输出权限流:加载中始终返回false;加载结束时先返回false锁定输出,100ms后返回true解锁。 distinctUntilChanged避免权限状态重复触发,提升性能。- 最终通过
filter只放行权限为true的值。
内容的提问来源于stack exchange,提问作者Andrey W
相关产品推荐
相关产品推荐

