Consider the following stream:
interval(1000)
.pipe(
take(5),
concatMap((val) => {
console.log(val, 'process');
return of(val).pipe(delay(3000));
})
)
.subscribe((val) => console.log(val, 'emit'));
As expected, 0 emits and hits the concat map. We see 'process' logged. During this time, 1 and 2 have emitted from the source. What i'd like to do is say "Now that my concatmap has finished, give me all items that are currently in the stream." So the next emit would be [1, 2], and we would see '[1,2] process'.
I am not sure how to achieve this. I have tried using a buffer and emitting every time concatMap emits, but it never gets an initial emit on that buffer, which resorted in hacking with timers and race and even then it did not work very well.
This is my current solution:
const dequeueSignal$ = new Subject();
interval(5000)
.pipe(
buffer(dequeueSignal$),
concatMap((val) => {
console.log(val, 'process');
return of(val).pipe(
delay(getRandomInt(20000)),
tap(() => dequeueSignal$.next(null))
);
})
)
.subscribe((val) => console.log(val, 'emit'));
dequeueSignal$.next(null)
This is the closest I can get. This means that if theres nothing in the buffer, it still emits and the cycle continues. However, this has major drawbacks:
- While nothing is in the queue, its constantly looping (the delay is only there for debug purposes. In my real scenario, this is a http call)
- Relies on an external call to start the whole thing off.
As such, this feels hacky and brittle. Is there an operator set I can use to create this scenario?