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

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

1 Comment

I like this answer, I think you can use forkJoin as well.
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

1 Comment

Updated, as await cannot be used outside async function

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.