Fields in my case can be finalized (actions linked to a field were executed). When they are done, I need to update 2 lists:
- alreadyExecutedFields: string[] --> plain array
- remainingFieldsToExecute: BehaviorSubject<string[]> --> behavior subject, because a .next needs to trigger other logic. This logic can be triggered parallel, but I want to prevent that because there's a splice within this logic which can behave incorrect then. (splicing an index, that was removed in the parallel chain.)
So when a field needs to be finalized, I call:
this.finalize$.next(field);
And the finalize$ chain looks like this:
this.finalize$.pipe(
concatMap((field: string) => {
return new Promise<void>((resolve) => {
console.log('START', field);
this.alreadyExecutedFields.push(field);
const remainingFieldsToExecute = this.remainingFieldsToExecute$.value;
remainingFieldsToExecute.splice(remainingFieldsToExecute.indexOf(field), 1);
this.remainingFieldsToExecute$.next(remainingFieldsToExecute);
console.log('END', field);
resolve();
});
}),
).subscribe(() => { });
But for some reason, when 2 finalize$.next calls happen right after each other, the concatMap doesn't await the promise of the previous one. Also when I tried to put a timeout around the END log and the resolve, it doesn't await the previous resolve.
What does work in my case is instead of using a concatMap, using a setInterval with a flag, which locks the part of the code where the lists are being updated.
But how can this be done in a better way? Or in a correct way with or without concat pipes.