Search code examples
angularasynchronousrxjsqueue

Queue up same observables to go in order in Angular 14 with rxjs


Currently I have code like this:

testReports() {
  this.dataSeries.forEach((x, index) => {
    setTimeout(() => {
      x.Status = FileStatus.PENDING;

      this._service.validateReport(x.Location).subscribe({
        next: y => this.convertResponseToGridView(y, x),
        error: () => console.error('Issues in validation')
      });
    }, index * 1500)
  });
}

I was curious if there was a better way to do this with rxjs. I do not know know the number of observables obtained from 'this.dataSeries' as they essentially strings of locations that may change from an end user input. They are obtained and then the 'this._service.validateReport(x.Location).subscribe...' kicks off to get data. It all works but number of 1500 milliseconds is more of a guess and sometimes the thread is further along or not. Is there a better way to do some operation if you do NOT know the observables statically?

I looked up this answer: How to make one Observable sequence wait for another to complete before emitting? and concat seemed promising but I was not sure if you could use that with some method predetermined to make an array of observables before executing it. Any help is much appreciated.


Solution

  • You can map your array of dataSeries to an array of the corresponding requests and then use concat to execute them all sequentialy.

    testReports() {
      //map each element of the array to the request observable
      const requests = this.dataSeries.map((x) => 
        this._service.validateReport(x.Location).pipe(
          tap({
            subscribe: () => x.Status = FileStatus.PENDING,
            next: y => this.convertResponseToGridView(y, x),
            error: () => console.error('Issues in validation')
          })
        )
      );
      
      //execute them all sequentially
      concat(...requests).subscribe();
    }