Anton Moiseev
Anton Moiseev

Reputation: 2874

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.

Upvotes: 3

Views: 3217

Answers (2)

Simon_Weaver
Simon_Weaver

Reputation: 145950

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));
}))

Upvotes: 1

martin
martin

Reputation: 96889

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

Upvotes: 1

Related Questions