Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 - How to chain async service calls (http requests) in a component?

I have a component which first need to call a service that POST something. Then in the same component I want to wait until the POST is done, to call another service which GETs data.

How can I make the GET call wait for the POST call to finish?

In new-version.component.ts:

private createNewVersion(value) {
    ...

    // create new version, then call on all available versions

    // POST call
    this._newVersionService.createNewVersion(vnr);

    // GET call
    this._versionService.getAvailableVersions(); 

    ...
}

In new-version.service.ts:

export class NewVersionService {

response$: Subject<any>;

constructor(private _http: Http) {
    this.response$ = new BehaviorSubject<any>(null);
 }

public createNewVersion(versionNr) {    
    this._http.post('http://localhost:8080/services/' + versionNr, null, {
        method: 'POST',
    })
    .subscribe(response => {
        this.response$.next(response.status);
    },
    error => console.error(error));
}

Thanks!

like image 579
Sojye Avatar asked Feb 03 '16 09:02

Sojye


2 Answers

When a call returns a Promise chain the calls with

someFunction() {
  return returnsPromise()
    .then(result => doSomethingNext())
    .then(result => doSomethingAfterThat());
}

Ensure you have a return that returns the Promise of that chain so the caller of someFunc() also has a chance to time additional work to execute after doSomethingAfterThat() is completed.

When a call returns an Observable then use the complete callback

someFunction() {
  return returnsObservable()
    .subscribe(
      event => doForEachEvent(),
      error => handleError(),
      () => doSomethingNext()
          .then(result => doSomethingAfterThat());
}

doSomethingNext() is executed after the last event and doSomethingAfterThat() is again chained with then() to show how to mix observable and promise. doSomething().

like image 106
Günter Zöchbauer Avatar answered Oct 16 '22 15:10

Günter Zöchbauer


You should be able to concat to achieve sequence, and reduce to collect the emitted values:

var a = this._newVersionService.createNewVersion(vnr);
var b = this._versionService.getAvailableVersions(); 

Rx.Observable.concat(a, b).reduce((acc:Array<any>, x:any) => {
    acc.push(x); return acc;
}, []).subscribe(t=> { 
      var firstEmitted = t[0];
      var secondEmitted = t[1];
});
like image 43
pixelbits Avatar answered Oct 16 '22 15:10

pixelbits