Dynamically filtering rxjs stream

泄露秘密 提交于 2019-12-24 01:27:29

问题


I'm using RXJS and I'm looking to dynamically filter the data, but I'm having problems:

let numberSource: ReplaySubject<Number> = new ReplaySubject<Number>();
let numberFilter: BehaviorSubject<Number> = new BehaviorSubject<Number>(5);

let filteredData = numberSource.filter(n => n < numberFilter.value);
numberFilter.subscribe(newFilter => {
  filteredData = numberSource.filter(n => n < newFilter);
  filteredData.subscribe(console.log);  // <- I think this is wrong
});

console.log("A");
filteredData.subscribe(console.log);

numberSource.next(1);
numberSource.next(10);
numberSource.next(100);

console.log("B");
numberFilter.next(50);

What I am doing is subscribing to numberSource, that is the data I am interested in displaying. I am also subscribing to numberFilter, because I want any changes to that to replay the subject, but I think I have done that wrong.

I am expecting to see:

A
1
B
1
10

I am seeing:

A
1
1
B
1
10

Can anyone help?


回答1:


I think I understand what you're trying to do. You want to stack all value emitted by numberSource to be able to reemit and filter them when numberFilter changes.

The major problem in your implementation is that numberFilter is a BehaviorSubject which emits its default value (5 in this case) every time you subscribe to it which happens right on the line numberFilter.subscribe(newFilter => .... This callback subscribes to filteredData and then again right after console.log("A");. So you haven't even started emitting data to numberSource and you've already subscribed twice. That's why it gives you 1 two times.

Easy solution is to use classic Subject and remember to unsubscribe() the previous subscription to filteredData:

let numberSource: ReplaySubject<Number> = new ReplaySubject<Number>();
let numberFilter: Subject<Number> = new Subject<Number>();

var subscription;
numberFilter.subscribe(newFilter => {
  if (subscription) {
    subscription.unsubscribe();
  }

  subscription = numberSource.filter(n => n < newFilter)
    .subscribe(console.log);
});

numberFilter.next(5);

console.log("A");

numberSource.next(1);
numberSource.next(10);
numberSource.next(100);

console.log("B");
numberFilter.next(50);

See live demo: http://plnkr.co/edit/vOaD8tcWlLRdfzU14Ufw

Now it gives you the output you wanted.



来源:https://stackoverflow.com/questions/40533450/dynamically-filtering-rxjs-stream

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