为什么RxJs的pipe中filter操作符会放行非true值?
问题原因分析
- 核心原因是RxJS中
toPromise()的默认行为不符合你的预期:toPromise()会在Observable触发complete信号时执行resolve逻辑,无论Observable是否有发送过有效值。你使用of(classA.var1)创建的是冷Observable,发送一次值后会立刻触发complete信号:当var1为false时,filter操作符会过滤掉该值,Observable没有发送任何值就完成,toPromise()依然会返回resolve状态的Promise(值为undefined),所以then代码块会被执行。 - 次要潜在问题:
of(classA.var1)只会在实例化Class B时取一次classA.var1的当前值,后续你修改classA.var1时var2$不会同步更新,也可能导致逻辑不符合预期。
修复方案
方案1:使用RxJS 7+ 新增的Promise转换API(推荐)
RxJS 7开始官方废弃toPromise(),替换为firstValueFrom和lastValueFrom,这两个API在Observable没有发送任何值就完成时,会直接抛出EmptyError进入catch逻辑,符合你的预期:
import { firstValueFrom } from 'rxjs'; FilterObservableValue(){ firstValueFrom( this.var2$.pipe( filter( x => x === true) ) ) .then(() => { // 只有filter放行后才会执行此处 }) .catch(err => { // 无值时会进入此处 console.log(err); }); }
方案2:兼容旧版本RxJS,新增throwIfEmpty操作符
如果还在使用RxJS 6及更早版本,可以在pipe中加入throwIfEmpty操作符,无值完成时主动抛出错误:
import { throwIfEmpty } from 'rxjs/operators'; FilterObservableValue(){ this.var2$.pipe( filter( x => x === true), throwIfEmpty() ) .toPromise() .then(() => { // 只有filter放行后才会执行此处 }) .catch(err => { // 无值时会进入此处 console.log(err); }); }
方案3:需要监听var1动态变化的场景
如果你的var1会动态更新,不要用of创建Observable,改用BehaviorSubject封装:
class A { private _var1 = new BehaviorSubject<boolean>(false); var1$ = this._var1.asObservable(); setVar1(val: boolean) { this._var1.next(val); } } class B { constructor(private classA: A) {} FilterObservableValue(){ firstValueFrom( this.classA.var1$.pipe( filter( x => x === true), take(1) // 取第一个匹配的值就结束 ) ) .then(() => { // 业务逻辑 }) .catch(err => console.log(err)); } }
内容的提问来源于stack exchange,提问作者JaySym
相关产品推荐
相关产品推荐

