简体   繁体   中英

Asynchronous Calls in Angular4

I am sure this question has been asked before, but I also believe my usecase is quite different.

I am using Angular 4. I have a service which calls a http get request fetching a list of items. Each item fetched contains data in set of firstname, lastname, dob of a person.

So while I make this request, I also need to make another series of http get requests, for each item in the list sending firstname, lastname, dob for each item and get the address and set it for each item of the list in my UI.

I need a non blocking asynchronous way to handle it.

Right now this is the way I am handling it, and my UI loads the whole template and the first item immediately. And then it fetches the second api and updates that data before populating the rest of the items from the first api.

Thus, the loading of the page looks really inconsistent and slow.

Please review the code below and suggest.

// the below service is the http request to get the list of items.

this._searchService.search(data).subscribe(
    resp => {
        this.loadaddressforeachitemindata(resp);
        this.onSuccess(resp);
    }, (error) => {
        this.loaderService.display(false);
        console.log("Error in search---"+error);
        this.errorMessage = "Internal Server Error, please try after some time ";
});  

The onSuccess() method gets the response and sets the data into a model

onSuccess(data: Response) {
    this.results = this.service.buildResult( data.json().response);
    this._router.navigateByUrl('/dashboard/landing/(view:people/person/results)');
}

The buildresult sets the data into my model class of results which is as follows:

export class PersonResults {
    firstname?: any;
    lastname?: any[];
    dob?: any[];
    address: any[];
}

The loadaddressforeachitem() method contains a for loop to iterate through the whole list calling a http get request for data set of every item fetched in the first http request

loadaddressforeachitem(data:Response){
    for(let i = 0; i<numberofiteminlist ; i++){
        let rowdata = data.json().response.person[i]
        let firstname = rowdata.names.name.firstName;
        let lastname = rowdata.names.name.lastName;
        let dob = rowdata.DOBs.DOB;
        let addresssearchparams = ({ firstName : firstname, lastName : lastname, dob: appdob });
        this.service.getAddressData(addresssearchparams).subscribe(
            res => {
                this.service.storeaddressdata(res)
        })
    } // end of for loop
} // end of loadaddressforeachitem method

The storeaddressdata() is a method in the service to push address returned for each item onto an array "address" field in the model of my data mentioned above.

Instead of waiting to get all the addressInformation against each item , I would suggest once you get the addressInformation of one person , update the UI at the same time. So user will get a nice experience of loading the data one by one and browser will not wait for all the asynchronous call to complete.

For that you don't need a big change , simple change would be move the loadaddressforeachitem in to your component and update the scope of the UI on getAddressData subscribe callback

loadaddressforeachitem(data:Response){
        for(let i = 0; i<numberofiteminlist ; i++){
             let rowdata = data.json().response.person[i]
                  let firstname = rowdata.names.name.firstName;
                  let lastname = rowdata.names.name.lastName;
                  let dob = rowdata.DOBs.DOB;
                  let addresssearchparams = ({ firstName : firstname, lastName : lastname, dob: appdob });
          this.service.getAddressData(addresssearchparams).subscribe(
            res => {
                 //here you can update the UI scope or append new address data in the scope 
          })
  } // end of for loop
} 

Or if you don't want to move the logic from the service, you can send a notification by using RxJS Subject with the data in to the component. From the component you can recieve the notification and update the UI with the data you are passed as a parameter.

https://ncjamieson.com/understanding-subjects/

You can also use Angular EventEmitter which is similar to RxJS Subject

https://angular.io/api/core/EventEmitter

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