Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return Observable from RxJS filter() predicate

Is there an operator in RxJS that works like filter() but accepts a predicate that allows returning an Observable? So when the Observable returned by the predicate emits an event filter() decides whether event from the original source should be discarded or not.

like image 597
Anton Moiseev Avatar asked Mar 20 '26 11:03

Anton Moiseev


2 Answers

If I understand you correctly I'd do it like the following:

const Observable = Rx.Observable;
const Subject = Rx.Subject;

let subject = new Subject();

source = Observable.from([1,2,3,4])
  .flatMap(val => subject
    .withLatestFrom(Observable.of(val), (_, val) => val)
    .filter(val => val % 2 == 0)
  );

source.subscribe(val => console.log(val));

subject.next(null);
setTimeout(() => {
  subject.next(null);
}, 1000);

I wrapped each value with another Observable and withLatestFrom operator that emits only when its source emits. In my case the source is subject so I have full control over it. Then there's filter() that can filter whatever you want.

Although, I wonder if there's any easier solution...

This prints only two values and after 1s another two because I called subject.next(null); inside the setTimeout callback:

2
4
2
4

See live demo: https://jsbin.com/gasumiz/10/edit?js,console

like image 56
martin Avatar answered Mar 23 '26 10:03

martin


Another way is using two switchMap operators:

const animals$ = from(['cat', 'dog', 'fish']).pipe(switchMap(animal => {

    // call webservice to determine if the animal is a mammal or not
    // this returns an observable boolean (i.e. a predicate)
    // this could be any Observable<boolean> of course
    const isMammal$: Observable<boolean> = webService.isMammal(animal);

    // when we get the result back if it's true then return the 
    // original 'animal' string (by creating a new observable with of()) 
    // if it isn't an animal then return EMPTY, which has the same effect as filtering it out
    return isMammal$.pipe(switchMap(isMammal => isMammal ? of(animal) : EMPTY));
}))
like image 44
Simon_Weaver Avatar answered Mar 23 '26 08:03

Simon_Weaver