javascriptrxjs

Rxjs iif or simple if


I have the following code:

obs.pipe(
   switchMap((val) => {
       // some logic...
       return iif(() => condition, someObservable())
   })
);

I am just wondering why couldnt this have been achieved with a simple if instead of the iif?

 if (condition) {
    return someObservable();
 }

Solution

  • Take a look at the implementation of iif:

    export function iif<T = never, F = never>(
      condition: () => boolean,
      trueResult: SubscribableOrPromise<T> = EMPTY,
      falseResult: SubscribableOrPromise<F> = EMPTY
    ): Observable<T|F> {
      return defer(() => condition() ? trueResult : falseResult);
    }
    

    iif is using defer to only call the condition function and pick an (inner) Observable when the (outer) Observable is subscribed to. This doesn't really make a difference when used inside switchMap because the code inside switchMap is executed on every emit, but results in different behaviour when you use iif to create an Observable and subscribe to it at a later time.

    const { iif, of, concat } = rxjs;
    
    let subscribeToFirst;
    const obs$ = concat(
      iif(() => subscribeToFirst, of('iif-first'), of('iif-second')), // use 'iif'
      subscribeToFirst ? of('if-first (never logged)') : of('if-second') // use 'if'
    );
    
    // Change at runtime which Observable will be subscribed
    // works for 'iif' but not for 'if'
    console.log('----- subscribe to first -----');
    subscribeToFirst = true;
    obs$.subscribe(value => console.log(value));
    console.log('----- subscribe to second -----');
    subscribeToFirst = false;
    obs$.subscribe(value => console.log(value));
    <script src="https://unpkg.com/rxjs@7.8.1/dist/bundles/rxjs.umd.min.js"></script>

    Apart from that the documentation also says that iif exists for convenience:

    Actually iif can be easily implemented with defer and exists only for convenience and readability reasons.