Angular 2 wait until all http.put from end of loop

I have a question. In my program, I need to update several records on the server, so I need to do this through a loop. But I need to get new information from the server. The problem is, how can I wait for a response on all http.put from 201?

Now some code: I have an update function inside a service:

public updateDataonServer(rodz: string, id: number, bodyContent: any) {
let body = JSON.stringify(bodyContent);
let headers = new Headers({ 'Content-Type': 'application/json' });
this.currentUser.setHttpHeader(headers);

let options = new RequestOptions({ headers: headers });

return this._http.put(serverAdress + '/rin/' + rodz + '/' + id,
  body,
  options).map(res => res.status).catch(this.handleError);

      

}

and i use it in this function:

changeShow(showId: number, oldShow: MpGruppedGroup[]) {
    for (var show of oldShow) {

        var paramsDict = {
            'DAILY_PLAN_GROUP_ID': show.dailyPlanGroupId,
            'DAILY_AIRINGS': show.dailyAirings,
            'SHOW_ID': showId
        };

        this.manager.updateDataonServer('MP_GROUPED', show.dailyPlanGroupId, paramsDict).subscribe((data: any) => {
            console.log('status ', data);
        });
    }


    // that should be done after all updates return 201 status
    this.getShowDayGroups(showId);
}

      

+3


source to share


2 answers


You can use async/await

. First mark updateDataonServer

as asynchronous and change the way http is called like this:

public async updateDataonServer(rodz: string, id: number, bodyContent: any) : Promise<any> {
let body = JSON.stringify(bodyContent);
let headers = new Headers({ 'Content-Type': 'application/json' });
this.currentUser.setHttpHeader(headers);

let options = new RequestOptions({ headers: headers });

const res = await this._http.put(serverAdress + '/rin/' + rodz + '/' + id,
  body,
  options).toPromise();
return   res.status;
}

      

Then we return the value then()



changeShow(showId: number, oldShow: MpGruppedGroup[]) {
    for (var show of oldShow) {

        var paramsDict = {
            'DAILY_PLAN_GROUP_ID': show.dailyPlanGroupId,
            'DAILY_AIRINGS': show.dailyAirings,
            'SHOW_ID': showId
        };

      this.manager.updateDataonServer('MP_GROUPED', show.dailyPlanGroupId,
            paramsDict).then(data=> console.log('status ', data));


    }


    // that should be done after all updates return 201 status
    this.getShowDayGroups(showId);
}

      

Please see this and in case you have any problem converting observable HTTP to Promise take a look at this answer

+1


source


You can use RxJS to achieve your desired result:

 //extracts the params needed for the put request,
 // and returns the result of http.put 
 // it DOES NOT subscribe to the http.put
updateSingleShowOnServer(show) {
   ....
   // use this function to encapsulate extracting the values from
   // your 'show' object and constructing your http.put request
}

// accepts an array of 'shows' and 
// returns an observable that emits after every single put request
// has returned a value
updateMultipleShowsOnServer(shows) {

   // convert your array of shows into an array of put requests to update shows
   let requests$ = shows.map( show => this.updateSingleShowOnServer(show) );

   // return an Observable that waits until each request in the requests array
   // outputs a value before emitting a value.
   // you are going to subscribe to the observable output from this method
   return Observable.combineLatest(requests$);
} 

      

My apologies for killing the method names a bit, but I did this to better explain to you what the methods do. Feel free to use your own names in your code.

But using these methods yours changeShow

will become:



changeShow(showId: number, oldShow: MpGruppedGroup[]) {

    // IMPORTANT - if any put request fails, this combined request will also fail, 
    // so you might want an error handler on your subscribe
    updateMultipleShowsOnServer(oldShow).subscribe(results => {

       // result is an array of the results of all put requests.
       this.getShowDayGroups(showId);         
   }, errors => {

       // Optional - do something if you got an error in one of the requests
   })

}

      

Additional note

  • remember to import Observable.combineLatest using `import 'rxjs / add / observable / combinationLatest'

  • combineLatest

    will work here because each HTTP request observable emits only once. if, however, you have multiple outliers per observable, there zip

    might be a better operator. I prefer combineLatest

    it because it tends to be more useful. You must read both statements to understand the differences.

  • if that second point doesn't make sense, read a little more on RxJS in general - it's a powerful tool for your toolbox

+2


source







All Articles