Filtering a BehaviorSubject

萝らか妹 提交于 2020-05-15 06:43:06

问题


I have a BehaviorSubject that I'd like to be able to filter, but maintain it's behavior-subject-like quality that new subscribers always get a value when they subscribe, even if the last value emitted was filtered out. Is there a succinct way to do that using built-in functions from rxjs? For example:

const isEven = (n) => n % 2 === 0;
const source = new BehaviorSubject(1);
const stream = source.pipe(filter(isEven));
stream.subscribe((n) => console.log(n)); // <- I want this to print `1`
source.next(2); // prints `2`; that's good
source.next(3); // does not print anything; that's good

I've written my own implementation, but would prefer a simpler solution using existing operators instead if it's easy.


回答1:


Just use a second BehaviorSubject

const { BehaviorSubject } = rxjs;
const { filter} = rxjs.operators;

const isEven = (n) => n % 2 === 0;
const source = new BehaviorSubject(1);
const stream = new BehaviorSubject(source.getValue());

source.pipe(filter(isEven)).subscribe(stream);

stream.subscribe(val => { console.log(val); });
source.next(2);
source.next(3);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>



回答2:


Your stream has already been piped to use the isEven filter, so your initial value of 1 is not shown in your console is behaving as expected.

If you want to see your initial value of 1, subscribe directly to the BehaviourSubject:

const isEven = (n) => n % 2 === 0;
const source = new BehaviorSubject(1);
const stream = source.pipe(filter(isEven));

// should print 1, and should print 2 and 3 when your source is nexted.
source.subscribe((n) => console.log(n)); 

stream.subscribe((n) => console.log(n)); // <- should NOT Print 1, because it has been filtered
source.next(2); // prints `2`; that's good
source.next(3); // does not print anything; that's good



回答3:


Adrian's answer gets the credit, it looks like he answer the best way given the built-in operators available with rxjs itself. It didn't quite meet my needs, so I published my custom operator in my little library s-rxjs-utils. It it called filterBehavior(). From the docs:

Works like filter(), but always lets through the first emission for each new subscriber. This makes it suitable for subscribers that expect the observable to behave like a BehaviorSubject, where the first emission is processed synchronously during the call to subscribe() (such as the async pipe in an Angular template).



来源:https://stackoverflow.com/questions/55526731/filtering-a-behaviorsubject

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!