Search code examples
angularangular6subscriptionsubscribe

(Angular 2/4/5/6) Nested subscribe methods with multiple http requests


I need to call a subscribe method within a subscribe method.

In the first subscribe method, it returns me a deviceid which is subsequently used in the second subscribe method.

result=[];
idArray=[2,4];

this.subscription =
    this.quoteService.get(this.quoteid) //first api call
     .subscribe((quote: Quote) => {   
       this.deviceid = quote["deviceid"]; 
       this.faultService.get(this.deviceid) //second api call
        .pipe(first())
        .subscribe((faultGroup: FaultGroup[]) => {
        faultGroup.forEach(({ faults }) => {
          //execute logic for 2nd subscription
          if (faults) {
            faults
              .filter(
                ({ id }) => this.idArray.indexOf(id) > -1,
              )
              .forEach(fault => this.result.push(fault.name));
          }
          //end of logic
        });
      });
    subscription.unsubscribe();
  }
});

Can someone teach me how to use flatMap/switchMap to avoid using a nested subscribe? Appreciate your help!


Solution

  • Here your requirement is to return then result from the second API, it's just that to call the second API, you need the result from the first. For this, switchMap() suites you best. Use it like explained in the code.

    this.subOb = this.quoteService.get(this.quoteid) //first api call
        .pipe(switchMap((quote: Quote) => {
              // result of first API call here
            this.deviceid = quote["deviceid"];
              // you need to return the second observable from inside the switcMap
              // and this will only be executed after the first Observable(first API call) is finished
            return this.faultService.get(this.deviceid) //second api call
              // need some mode logic after second API call is done? call first()?
              // map the result with a pipe
                .pipe(map(secondData) => { 
                      // If you aren't manipulating the data 
                      // to be returned, then use tap() instead of map().
                    return data;
                })
    
        }))
            .subscribe((data) => {
                // only one subscription is required.
                // this will have data from second API call
            })
    

    Use the ngOnDestroy() hook to unsubcribe() for the Subscriptions. I see that you are assigning the subscription to a variable and probably uing the same to unsubscribe. If your Observable emits multiple time(which I think it doesn't) then during the first emission when it comes to subscribe(), the "subscription" variable will be undeifned.

    ngOnDestroy() {
        if (this.subOb) {
            this.subOb.unsubscribe();
        }
    }
    

    See a sample example here: https://stackblitz.com/edit/swicthmap?file=src%2Fapp%2Fapp.component.ts

    It contains two implementations of switch maps, analyze both and use whatever suites you.