Monday, July 30, 2018

RxJs observable tip - DON'T subscribe inside subscribe

Hi,

I've been working with RxJs observable for a while and I have a little tip for rxjs starters: 
Don't subscribe inside subscribe!

For some of you it may seem obvious but let me explain.



The Don't

this.observableGeneratorService.getBooleanObservable().subscribe((shouldPresentNumbers) => {
      if(shouldPresentNumbers) {
        this.observableGeneratorService.getNumberObservable().subscribe((val) => {
          this.uglyNumbers.push(val);
        })
      }
    });

In this case:
1. getBooleanObservable gets executed
2. A response received into shouldPresentNumbers
3. If shouldPresentNumbers is true => getNumberObservable is executed
4. A response received into val

We want to keep this executive order but not using this anti-pattern. What if we had more service calls? Then we had to deal with "Callback" hell. It's really unnecessary when rxjs library has so many methods that help to manipulate data (take a look at https://www.learnrxjs.io/ ).

Right way


this.goodObservable$ = this.observableGeneratorService.getBooleanObservable()
    .concatMap((shouldPresentNumbers) => {
      let numbersObservable = shouldPresentNumbers ? this.observableGeneratorService.getNumberObservable() : Observable.empty();
      return numbersObservable;
    }) // concatMap would map "true" to each emitted value (1,2,3,4,5) and creates an observable.
    // Finally it returns: Observable of 1,2,3,4,5
    // this could also be done by using ".map(...).combineAll()"
    .toArray(); // turn into an array of observable

concatMap allows returning an observable from inner method. In contrast to map which wraps inner method with an observable (It's possible to use map and combineAll right after).
That's it. Now it's possible to use subscribe once and finish this thing off.
Now we can even get a  nice performance boost that we've couldn't get earlier.
An html element can subscribe to the observable result by using async pipe!
toArray is used in order to turn Observable.of(1,2,3,4,5) into [Observable.of(1,2,3,4,5)]. 
With this data type - it's possible to use it in a template view like:

 <li *ngFor="let good of goodObservable$ | async">
     {{good}}
    </li>

Thank you Blogger, hello Medium

Hey guys, I've been writing in Blogger for almost 10 years this is a time to move on. I'm happy to announce my new blog at Med...