Running group of observables in chunks in RxJS

Viewed 479

I am trying to run a pool of observables in chunks and add an interval in between. I tried below code:

    let i = 0;
    from([].constructor(20)).pipe(
      concatMap(a => of(i).pipe(delay(1000))), // add a delay
      mergeMap(obj => of(i++), 5) // run 5 in parallel
    ).subscribe(res => {
      console.log('done', new Date().toISOString(), res);
    });

Now this adds delay to all the observable so the output I get is:

done 2020-03-25T09:23:34.151Z 0
done 2020-03-25T09:23:35.151Z 1
done 2020-03-25T09:23:36.151Z 2
done 2020-03-25T09:23:37.151Z 3
done 2020-03-25T09:23:38.151Z 4
done 2020-03-25T09:23:39.151Z 5
done 2020-03-25T09:23:40.153Z 6
done 2020-03-25T09:23:41.155Z 7
done 2020-03-25T09:23:42.161Z 8
done 2020-03-25T09:23:43.163Z 9
done 2020-03-25T09:23:44.167Z 10
done 2020-03-25T09:23:45.170Z 11
done 2020-03-25T09:23:46.171Z 12
done 2020-03-25T09:23:47.177Z 13
done 2020-03-25T09:23:48.178Z 14
done 2020-03-25T09:23:49.182Z 15
done 2020-03-25T09:23:50.183Z 16
done 2020-03-25T09:23:51.186Z 17
done 2020-03-25T09:23:52.188Z 18
done 2020-03-25T09:23:53.192Z 19

As you can see it runs each of them and adds 1 second delay. What I want to achieve is run first 5 parallel and then add 1 second delay and then run next five and so on.

I even tried swapping mergeMap and concatMap order in the pipe, but it gives same result.

Any thoughts on how to do that?

1 Answers

You can use bufferCount to create batches then forkJoin to run them in parallel:

let i = 0;
const createRequest = () => of(i++);

from([].constructor(20)).pipe(
  bufferCount(5),
  concatMap(chunk => forkJoin(chunk.map(createRequest))
    .pipe(delay(1000)) // add a delay
  ),
).subscribe(res => {
  console.log('done', new Date().toISOString(), res);
});

Live demo: https://stackblitz.com/edit/rxjs-jvhvqx

Related