简体   繁体   中英

How to filter RXJS BehaviorSubject

I want to filter data with BehaviorSubject. When i try with:

   public accounts: BehaviorSubject<any> = new BehaviorSubject(this.list); 
    this.accounts.pipe(filter((poiData: any) => {
      console.log(poiData)
    }));

No work and bellow (poiData: any) is line error with text:

No overload matches this call. Overload 1 of 2, '(predicate: (value: any, index: number) => value is any, thisArg?: any): OperatorFunction<any, any>', gave the following error. Argument of type '(poiData: any) => void' is not assignable to parameter of type '(value: any, index: number) => value is any'.

My question what is error? How to filter BehaviorSubject?

Your error is occurring because the function you are passing to filter() returns void instead of a boolean . You can resolve the error, but specifying an expression that evaluates to a boolean.

However, it looks like your BehaviorSubject emits an array:

   public accounts: BehaviorSubject<any> = new BehaviorSubject(this.list); 

And it looks like your intention is to filter the array. If this is the case, you don't want filter operator, because this will filter out emissions, which in your case, is the full array. Since you want to filter the emitted array, you should use the rxjs map operator to map the emitted array to an array which you filter using the js Array.prototype.filter function, like this:

   public accounts: BehaviorSubject<any[]> = new BehaviorSubject(this.list); 
   public filteredAccounts = this.accounts.pipe(
        map(poiDataArray => poiDataArray.filter(
            acc => {
                console.log(acc);
                acc => acc.id != this.anyId;
            }
        ))
    );

Here is a simplified StackBlitz example:

  public numbers$ = new BehaviorSubject<number[]>([]);
  public oddNumbers$ = this.numbers$.pipe(
    // map to new array that filters out even numbers
    map(numbers => numbers.filter(n => n % 2)),
  );

Your question doesn't make sense to me, but here some information that might help you solve your problem.

Array#filter vs RxJS#filter

JS's filter on arrays in pretty similar to RxJS's filter on Observables (Remember that Subjects are observables too)

For example, consider this predicate that returns true if a number is even

const even = n => n % 2 == 0

These two pieces of code are pretty similar:

const arr = [1,2,3,4,5,6,7,8,9];
console.log(arr.filter(even));

Output: [2,4,6,8]

const arr = [1,2,3,4,5,6,7,8,9];
from(arr).pipe(
  filter(even)
).subscribe(console.log);

Output:

2
4
6
8

In the first case, Array#filter returns an array where even returns true for every element in the array. The second version creates a stream where even returns true each element of the stream (after the filter).

Very similar.

Predicates

A predicate is pretty easy to spot. It returns a boolean value. True or false.

(any) => true  // This is a predicate
(any) => false // this is a predicate
(any) => void  // this is not a predicate.

This:

(poiData: any) => {
  console.log(poiData);
}

is the same as (any) => void . So you cannot use this to filter either an array or an observable.

Filtering an Observable vs Transforming an Observable

The most basic way you can transform an observable is with the map operator. Map changes the elements in your stream without effecting the stream directly (The number of emissions, their timing, ect).

It looks like maybe your observable is emitting an array (or list of some sort).

public accounts: BehaviorSubject<any> = 
  new BehaviorSubject(/* ---> */ this.list /* <--- */); 

In this case, it's possible that you're not looking to alter the stream, but rather its elements. Perhaps that might look like this:

accounts.pipe(
  map(list => list.filter(element => /* code that returns true or false */))
).subscribe(console.log);

But, of course, you can filter the stream itself as well in order to decide if the list being held by your BehaviourSubject is emitted by the corresponding observable.

accounts.pipe(
  filter(list => /* code that returns true or false */)
).subscribe(console.log);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM