RDV
RDV

Reputation: 1026

How to wait for http response before making backend call in Angular

I am new to angular, I am trying to make an http get request and based on its response, I have to make a backend call.

Here I am trying to chain 2 async calls, not sure if that is doable/correct approach in Angular (using Angular 7 version).

Problem Statement: Second (Backend) aysnc call is made before getting response from first (http) async call.

I tried implementing using async/await (understand not a correct way, but still tried) and calling backend call in subscription to 1st http call. Both approaches didnt work. Please let me know what is going wrong here and if there is a better way to chain 2 async calls.

Below is the code snippet (simplified version)

export class BasicService{ 
let httpUrl:string=null;
  constructor(protected http: HttpClient, protected backendSvc: BackendService) {
      httpUrl='/someUrl';
  }

  getComponentData(route: ActivatedRoute): Observable<ComponentData> {
    let callName:string;
    let inputPayload:string;
    let routeID=route.snapshot.url[0].path;

if (routeID.Equals('Test')) {
  callName='TestCall';
}
else if (routeID.Equals('Execute')) {
  callName='ExecuteCall';
}

//Failure#1: Get http response back and then call backendSvc, inputPayload remains empty
//want to wait for _waitCreateInputPayload to finish execution before calling backendSvc
inputPayload = this._waitCreateInputPayload(httpUrl,callName);  
//backendSvc returns an observable
return this.backendSvc.GetData(callName, inputPayload, null, this.FormFactorType);

//Failure#2: This approach also doesn't work.
this._createInputPayload(httpUrl,callName).subscribe(tempVal=>{
    if(tempVal!=undefined){
        return this.backendSvc.GetData(callName, tempVal, null, this.FormFactorType);
    }else{
        return null;
    }
});
  }

      private async _waitCreateInputPayload(httpUrl: string, callName:string){
        return await this.http.get(httpUrl, { responseType: 'text' }).subscribe(tempVal=>{
          console.log('in _createInputPayload');
          return tempVal;
        });
      } 


private _createInputPayload(httpUrl: string, callName:string): string{
    return this.http.get(httpUrl, { responseType: 'text' });
  } 
}

The component code looks like this:

    export class ChildTemplateComponent implements OnInit {

  constructor(protected basicSvc: BasicService, protected route: ActivatedRoute) {}

  ngOnInit() {
    this.formFactorSvc = this.route.snapshot.data['formFactor'];
    this.formFactorSvc.getDesignConfig(this.route);
  }

  ngInit() {
    this.basicSvc.getComponentData(this.route).subscribe((x) => {
      this.populateData(x);
    });
  }

  populateData(data: ComponentData){
  //populate the View
  }
}

Thanks,

RDV

Upvotes: 0

Views: 299

Answers (2)

iProgramGUIs
iProgramGUIs

Reputation: 164

using RxJs you can pipe the return from _createInputPayload, in the pipe you can tap the result from _createInputPayload into a member variable, then the mergeMap will call GetData. When you subscribe to getComponentData from the component the subscription will be to GetData since that's the last mergeMap.

return this._createInputPayload(this.httpUrl, callName).pipe( tap((input) => inputPayload = input), mergeMap(() => this.backendSvc.GetData(callName, inputPayload, null, this.FormFactorType)));

Upvotes: 1

Eden Koveshi
Eden Koveshi

Reputation: 61

_createInputPayload should return an Obseravble and not a string, as http.get returns an Observable. Once you change this, you could subscribe to it and then you'll get the http response before making the backend call.

Upvotes: 0

Related Questions