Wait for multiple Observables in Angular 5

Viewed 4780

I'm new in Angular and TypeScript, so question could sound wrong. I'm using Visual Studio Code and Angular 5 (ng-version="5.2.11").

I need to "await" till my call to api will end and return it's result without wrapping everything in giant ".subscribe". What I have:

exampleMethod(): SettingsClass {
const myComplexObject: SettingsClass = {
  field1: predefined.field1,
  field2: predefined.field2,
  field3: isComplexCalculationsNecessary ? this.CallApi_1(predefined.paramForField3) : predefined.field3,
};

return myComplexObject;
}

Previously I had all parameters in "predefined", but now I need to query one(or more) from external source, and immediately return "myComplexObject" from method (to some other api call, or other component, or even interface, but I need this object fully defined, with all parameters set). I could turn my code "upside-down" and put everything inside big ".subscribe", but I dont't, because at some point I will need other parameter to query as well, and all this will break. How to write call to api, to avoid rewriting all my code each time I need to add new external call? Something like:

CallApi_1(paramForField3: string): Observable<int> {
return this.http.get(`${httpConfig.route}?$apply=filter${paramForField3}/groupby${httpConfig.groupingParam}`);
}

OR maybe

CallApi_1(paramForField3: string): Observable<int> {
return this.ExternalCallsService.GetParam3Information(paramForField3).subscribe(res => 
.GetParam3Information contains the same http call as above, but I need to do
something to return this result outside, I don't know what);
}

What I'm looking for is some king of:

field3: isComplexCalculationsNecessary ? **await** this.CallApi(predefined.paramForField3) : predefined.field3,

I'm currently trying 'rxjs' that have interesting options to work with Observables, like 'forkJoin', but I'm not sure that I'm looking in the right direction entirely, maybe such a trick impossible, or my understanding of Observables is not right and I need to move complex logic to back-end? Please, advise.

Important to notice again, that simple ".subscribe" is not what I'm looking for, because in all subscribe-examples we are not returning values, but assigning it to some global variable or directly to html-element and it's NOT what I need, I need to get value and continue working with it as fast as external resource will return it.

3 Answers

You can use zip or forkjoin operators ( they are similar but not the same ) or you can chain your http calls :

this.http.get1( url1, headers ).subscribe(
   data => {
      this.data1 = data;
      this.http.get2( url2, headers ).subscribe(
         data => {
            this.data2 = data;
         },
         error2{
            // do something on error2
         }
      )
   },
   error1 => {
      // do something on error1
   }
)

This is not very nice but works ok. I remember using zip for solving the same problem.

Edit : I found the zip example

     const  tpcomprob$ = this.data.getTPComprob( this.tpcomprobsId);
     const  comprobs$ = this.data.getComprobs(this.tpcomprobsId); 

     this.sbsComprobs = zip(tpcomprob$, comprobs$, (tpcomprob: any, comprobs: any) => ({tpcomprob, comprobs}))
                       .subscribe(pair => {
                          this.tpcomprob = pair.tpcomprob;
                          this.comprobs = pair.comprobs;

        },
        error => {this.httpError = error ;})
  });

forkJoin is the easiest.

var _arr = [];

_arr.push(this.mySvc.callback01());
_arr.push(this.mySvc.callback02());

forkJoin(_arr).subscribe(resList=>{
    //-- the response will be in array
});

Related