1

I have an array of observables (HTTP POST requests) that I need to send off to an API after a specific event. The following is a simplified example of the approach, where I use concat so I can leverage success, error and complete callbacks.

// build up an array of stored POST requests to fire off later
// array is indeterminate length, could be 1 request could be 1,000
let requests = [ req1, req2, req3, req4 ];

concat(...requests).subscribe(
  success => ... handle success ...
  error => ... handle error ...
  () => ... handle completion ...
);

The issue is the concat basically sends all the requests at once, raising the potential for concurrency issues in the API consuming the requests. This issue should be resolved if I am able to fire the requests off one-by-one rather than all at once. I've determined that a forEach loop is not an option.

Is there an RxJS approach such that req2 only emits after req1 completes and req3 emits only after req2 completes and so on? I've been reviewing the RxJS docs but have yet to find anything that fits this scenario.

Nathan Beck
  • 1,152
  • 14
  • 23
  • Use async await for dependencies using closures. Convert observable to promises to get it done. – JWP Oct 10 '20 at 00:37
  • 2
    "The issue is the concat basically sends all the requests at once" -> `concat` should fire the observables sequentially, only moving on the subsequent requests after the first one has completed. [Example](https://www.learnrxjs.io/learn-rxjs/operators/combination/concat#examples) – BizzyBob Oct 10 '20 at 03:07
  • Your code with `concat` should work as intended. If it doesn't please provide a stackblitz that's reproducing the problem. – frido Oct 12 '20 at 11:46

1 Answers1

2

You could use RxJS from function and higher order mapping operator concatMap.

Try the following

from(requests).pipe(
  concatMap(req => req)
).subscribe(
  success => ... handle success ...
  error => ... handle error ...
  () => ... handle completion ...
);

Without the concatMap operator the request elements of the array would be verbatim emitted as observables instead of being triggered. You could find differences b/n higher order mapping operators in my other answer here.

ruth
  • 29,535
  • 4
  • 30
  • 57
  • 1
    @RafiHenig: `concat`'s supposed to send the requests sequentially. But you say _"(it) basically sends all the requests at once"_. And without seeing the nature of the requests, my answer is the next alternative I could come up with. It ensures the emissions are sequential. You could see the differences in this [Stackblitz](https://stackblitz.com/edit/angular-ivy-kfheyu?file=src/app/app.component.ts). – ruth Oct 11 '20 at 06:51
  • 1
    your example in stackblitz helped me a lot thanks ! – sohaieb azaiez Mar 08 '22 at 18:38