Angular RxJS: conditional operator (if else)

Viewed 19393

I'm trying to figure out how to implement a straightforward condional operation into an observable.

this.deactivate$
    .pipe(
        filter((canDeactivate) => !canDeactivate),
        switchMap(() => Observable.of(window.confirm("message")))
    );

What I want to get is that:

if (canDeactivate) {
    return canDeactivate;
}
else {
    return window.confirm("message");
}

The problem on first above code is that when I'm filtering emitted value, the rest of operators are not performed and stream stops to populate emitted value.

Any ideas?

4 Answers

You can decide which observable return inside the switchMap operator, like this:

    this.deactivate$
        .pipe(
            switchMap((canDeactivate) => {
               if (canDeactivate) {
                   return Observable.of(canDeactivate);
               }
               else {
                   return Observable.of(window.confirm("message"));
               }
            })
        );

Bonus (super shorter version):

this.deactivate$.pipe(
        switchMap((canDeactivate) => Observable.of(canDeactivate || window.confirm("message"))
    );

From documentation of rxjs

iif Decides at subscription time which Observable will actually be subscribed.

iif accepts a condition function and two Observables. When an Observable returned by the operator is subscribed, condition function will be called. Based on what boolean it returns at that moment, consumer will subscribe either to the first Observable (if condition was true) or to the second (if condition was false). Condition function may also not return anything - in that case condition will be evaluated as false and second Observable will be subscribed.

example

let accessGranted;
const observableIfYouHaveAccess = iif(
  () => accessGranted,
  of('It seems you have an access...'),
  of('Opps')
);

So if accessGranted is true it will execute the first of else second of

window.confirm is blocking so you can just use a map() operator. Calling switchMap to of(window.confirm(..)) will just stop the execution of JavaScript anyway.

this.deactivate$
    .pipe(
        map(canDeactivate => canDeactivate ? canDeactivate : window.confirm("message"))
    );

Little bit late but what about the partition operator ?

I find it more elegant when you have to deal with conditions and predicates: https://www.learnrxjs.io/learn-rxjs/operators/transformation/partition

const [canDeactivate$, cannotDeactivate$] = partition(this.deactivate$, (canDeactivate) => !canDeactivate);
// in case the condition !canDeactivate is true
canDeactivate$.pipe(switchMap(canDeactivate => of(...)).subscribe(...);
// in case the condition !canDeactivate is false
cannotDeactivate$.pipe(switchMap(() => of(window.confirm("message")))).subscribe(...);
Related