Menu

How to make HTTP calls inside a loop and wait for one to finish before making another?

September 1, 2019 - Javascript

1) using reduce() to Sequentially Resolve Promises Works

source: https://css-tricks.com/why-using-reduce-to-sequentially-resolve-promises-works/

let userIDs = [1,2,3];

userIDs.reduce( (previousPromise, nextID) => {
  return previousPromise.then(() => {
    return methodThatReturnsAPromise(nextID);
  });
}, Promise.resolve());

Or, in a more modern format:

let userIDs = [1,2,3];

userIDs.reduce( async (previousPromise, nextID) => {
  await previousPromise;
  return methodThatReturnsAPromise(nextID);
}, Promise.resolve());

2) Using modern js or RXJS

source: https://stackoverflow.com/questions/53923003/how-to-make-http-calls-inside-a-loop-and-wait-for-one-to-finish-before-making-an

If you are using promises and want to wait for each promise to resolve before another call is made then (1) you should not use Promise.all as this will wait til all requests are resolved and (2) you need to use a plain old for-loop which enables you to wait for async operations within the loop.

async processArray(array) {
  for(var i = 0; i < array.length; i++){
    await yourServiceCall();
  }
}

As a sidenote: Since you are using async-await, don’t forget to convert your observables to promises.

If you want to move away from promises (and async-await) and rely on pure RxJS instead, have a look at concatMap:

Projects each source value to an Observable which is merged in the output Observable, in a serialized fashion waiting for each one to complete before merging the next.

For example:

import { from } from 'rxjs/observable/from';

ngOnInit() {
  from(myArray)
    .pipe(concatMap(el => yourServiceCall(el)))
    .subscribe(/* your logic */);
}

Leave a Reply