3

I have a question. In my program i need to update few records on server so i need to do this throught the loop. And after all i need to get new infrmation from server. The problem is how can i wait till all http.put response with 201?

Now some code : I have an update function inside 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);
}
Przemysław Zamorski
  • 741
  • 2
  • 14
  • 31

2 Answers2

2

You can use RxJS to achieve what you want:

 //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 butchering your method names a bit, but I did that to better explain to you what the methods are doing. Feel free to use your own names in your code.

But, using those methods, your changeShow becomes:

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

}

Extra note

  • don't forget to import Observable.combineLatest using `import 'rxjs/add/observable/combineLatest'

  • combineLatest will work here because each http request observable only emits once. if however, you had multiple emissions per observable, zip might be the better operator to use. I tend to favour combineLatest because it tends to be more generally useful. You should read up on both operators to understand the differences.

  • if that second point doesn't make sense, read up on RxJS as a whole a bit more - it's a powerful tool to have in your toolbox

snorkpete
  • 14,278
  • 3
  • 40
  • 57
1

You can use async/await. First mark the updateDataonServer as async and change how the http is called as following:

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, get the return by 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 face an issue with converting the HTTP observable to promise, please have a look on this answer

Amr Eladawy
  • 4,193
  • 7
  • 34
  • 52