35

I have a situation like the following:

myObservable1.pipe(
  switchMap((result1: MyObservable1) => {
    if (condition) {
      return myObservable2;
    } else {
      return of(null);
    }
  })
).subscribe(myObservable1 | myObservable2) => {

So if condition is false I only have to perform one request, if the condition is true, I have to chain the first request to the following one, they are essentially two requests to the server api.

Is there a better solution without returning that null?
Is there any conditional operator in RxJs?

Thanks!

TmTron
  • 17,012
  • 10
  • 94
  • 142
user2010955
  • 3,871
  • 7
  • 34
  • 53
  • 2
    you can return `empty()` observable – martin May 21 '18 at 19:30
  • I tried, but it says: '[ts] Cannot invoke an expression whose type lacks a call signature. Type 'Observer' has no compatible call signatures. ' – user2010955 May 22 '18 at 08:13
  • Checkout this article that explains it all in depth: https://blog.strongbrew.io/rxjs-patterns-conditionally-executing-work/ – KwintenP Feb 22 '19 at 08:12

4 Answers4

27

Another possibility is to use the operator iif in a SwitchMap.

https://www.learnrxjs.io/learn-rxjs/operators/conditional/iif

https://rxjs-dev.firebaseapp.com/api/index/function/iif

but it can restrain the possibility to control specfic conditions on your Observable :

myObservable1
.pipe( 
      switchMap(result1 =>
               iif(() => condition
               , myObservable2
               , myObservable1
            )
      )
.subscribe(result => console.log(result)); 

Where you can replace 'condition' by a function returning a boolean. With a function :

myObservable1
    .pipe( 
          switchMap(result1 =>
                   iif(() => test(result1)
                   , myObservable2
                   , myObservable1
                )
          )
    .subscribe(result => console.log(result)); 

test(result1) : boolean {
     if(result1){
       // the iif() will return myObservable2
       return true;
     }else{
       /: the iif() will return myObservable1
       return false ;
     }
}

Like @amjuhire said , you can write with a filter and a switchMap :

myObservable1.pipe(
  filter((result1) => condition)
  switchMap((result1: MyObservable1) => {
    return myObservable2;
  })
).subscribe(result2 => { ... })

Another possibility given your example :

myObservable1.pipe(
  switchMap((result1: MyObservable1) => {
    if (condition) {
      return myObservable2;
    } else {
      return of(result1);
    }
  })
subscribe(result => console.log(result));

Or using EMPTY in the switchMap :

 myObservable1.pipe(
      switchMap((result1: MyObservable1) => {
        if (condition) {
          return myObservable2;
        } else {
          // Observable that immediately completes
          return EMPTY;
        }
      })
    subscribe(result2 => console.log(result2));

The problem here is that we don't know the type in your observable.

So i can't judge wich way is the better.

It also depends on how you want to handle the success/error between the different calls of your observable.

Koraxos
  • 418
  • 5
  • 13
18

No need to return of(null), you should use the RxJs filter operator

myObservable1.pipe(
  filter((result1) => condition)
  switchMap((result1: MyObservable1) => {
    return myObservable2;
  })
).subscribe((result2) => { ... })
jmuhire
  • 2,091
  • 21
  • 19
8

In my understanding, you shouldn't use filter operator because in that case you wouldn't get any value.

myObservable1.pipe(
  switchMap((value) => {
    return iif(() => condition, myObservable2, of(value));
  })
).subscribe((value) => console.log(value) // either from myObservable1 or from myObservable2)
DongBin Kim
  • 1,799
  • 5
  • 23
  • 43
  • I think that your answer is valid. But i'm not sur if the question asked specifically to catch a value from the first observable. If the filter returns true, it will execute the switchMap, else the observable1 will still execute even if it won't return any value – Koraxos Jun 30 '20 at 10:24
  • @Koraxos You may be right but given OP's code: `subscribe(myObservable1 | myObservable2)`, I assumed he/she was going to do something with the value either from obs1 or from obs1 * obs2. – DongBin Kim Jul 01 '20 at 04:42
  • yes i understand that , and that's why i said that youy answer is valid , i agree with you on that point. And that's why i think, if the question was a little more detail, we would be able to find the best answer – Koraxos Jul 01 '20 at 06:52
-1

I don't know your real code, this is the pseudo code, and I don't know which rxjs version are you using now, but you can do something like below:

assuming you are using rxjs 6:

iif(condition, obervable1, concatMap(observable1, observable2))
.subscribe()
Raj Baral
  • 661
  • 6
  • 19