Rani
Rani

Reputation: 111

Subscribe to multiple service call sequentially

i have to do 2 api call, i want first call to complete and then the second call to start sequentially. 2nd call dont have any dependency on first call. both the call makes update to the DB. if i use the below code, update to the second call is happening multiple times due to which it is trying update same record multiple time which i want avoid.any help is appreciated.

updateUserCommentsObservable(): Observable<any> {
  if (!this.userComments) {
    return EMPTY;
  }

  const source = this.arrayGroupBy<TrailerComparisonUserComment>(
    this.userComments, 
    comment => comment.trailerComparisonId);
  return from(Object.keys(source)).pipe(
    mergeMap(x => this.trailerComparisonService.updateUserComments(
      x, source[x])
    )
  );
}


this.updateUserCommentsObservable().pipe(
  flatMap(() => from(this.trailerComparisons).pipe(
    mergeMap(trailerComparison => 
      this.trailerComparisonService.saveReviewComplete(
        trailerComparison.trailerComparisonId))
    )
  )
).subscribe(() => {                   
  this.userComments = [];
  this.disableStage1Review = true;
  let snackBarRef = this.snackBar.open('Well done! Stage1 Review Complete has been successfully saved.', 'Dismiss');                   
}, error => {                   
  console.log("Error", error);
  let snackBarRef = this.snackBar.open('Error! ' + error.error.message, 'Dismiss');
});

Upvotes: 0

Views: 2749

Answers (2)

Kurt Hamilton
Kurt Hamilton

Reputation: 13515

You can run multiple observables sequentially using the concat function.

concat(
  obs1$,
  obs2$
).subscribe(result => {
  console.log(result);
});

If each observable returns 1 result and completes (an http request), then subscribe will receive 2 values - the result of obs1$ and then the result of obs2$.

If you want to wait for both to return a result, you can use the toArray function.

concat(
  obs1$,
  obs2$
).pipe(
  toArray()
).subscribe(result => {
  console.log(result);
});

The result in the subscribe will now be an array of obs1$ result and obs2$ result.

Your requirements are a bit more complex because you have an initial observable and then an array of observables. If you want to run your array of observables sequentially, then you can create the array of observables up front and pass them into concat.

const trailerComparisons$ = this.trailerComparisons.map(c => 
  this.trailerComparisonService.saveReviewComplete(c.trailerComparisonId)
);

concat(
  this.updateUserCommentsObservable(),
  ...trailerComparisons$
).pipe(
  toArray()
).subscribe(/* subscribe handling */)

DEMO: https://stackblitz.com/edit/angular-jldrrh

Upvotes: 1

Humberd
Humberd

Reputation: 2951

To make calls sequential you have to use concatMap instead of mergeMap.

https://rxjs-dev.firebaseapp.com/api/operators/concatMap

Upvotes: 0

Related Questions