简体   繁体   中英

Wait for multiple Observables in Angular 5

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.

You can use rxjs/concat , take a look on this example: https://stackblitz.com/edit/angular-functions-in-sequence?file=src%2Fapp%2Fapp.component.ts

It would be something like this first, second and so on are functions that returns Observables

let sequence = concat([
      this.first, 
      this.second, 
      this.afterSecond, 
      this.third]);

    sequence.subscribe(currentFunction => {
      currentFunction().subscribe(value => {
        this.values.push(value);
      })
    });

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 });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM