Los campos en mi caso se pueden finalizar (se ejecutaron acciones vinculadas a un campo). Cuando terminen, necesito actualizar 2 listas:
Entonces, cuando un campo necesita ser finalizado, llamo:
this.finalize$.next(field);Y la cadena finalize$ se ve así:
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(() => { });Pero por alguna razón, cuando 2 llamadas finalize$.next suceden una después de la otra, concatMap no espera la promesa de la anterior. Además, cuando traté de poner un tiempo de espera alrededor del registro END y la resolución, no espera la resolución anterior.
Lo que sí funciona en mi caso es, en lugar de usar un concatMap, usar un setInterval con una bandera, que bloquea la parte del código donde se actualizan las listas.
Pero, ¿cómo se puede hacer esto de una mejor manera? O de forma correcta con o sin tubos concat.
alreadyExecutedFields ya ejecutados, puede usar el operador de tap que se usó para los efectos secundariosremainingFieldsToExecute para ejecutar, puede usar withLatestFromremainingFieldsToExecute para ejecutar; puede volver a usar tap alreadyExecutedFields: string[] = []; remainingFieldsToExecute$: BehaviorSubject<string[]> = new BehaviorSubject< string[] >(['1', '2', '3', '4', '5']); finalize$ = new BehaviorSubject('1'); ngOnInit() { this.finalize$ .pipe( tap(field => this.alreadyExecutedFields.push(field)), withLatestFrom(this.remainingFieldsToExecute$), tap(([field, remainings]) => { remainings.splice(remainings.indexOf(field), 1); this.remainingFieldsToExecute$.next(remainings); }) ) .subscribe(([_, data]) => { console.group(); console.log('*** NEW EMIT ***'); console.log('current field:', _); console.log('remainingFieldsToExecute', data); console.log('alreadyExecutedFields:', this.alreadyExecutedFields); console.groupEnd(); }); this.finalize$.next('2'); this.finalize$.next('3'); }demostración: https://stackblitz.com/edit/angular-ivy-ensh7w?file=src/app/app.component.ts
registros:
Podría simplificarse a:
this.finalize$ .pipe( mergeMap(field => this.remainingFieldsToExecute$.pipe( map(remFields => { this.alreadyExecutedFields.push(field); remFields.splice(remFields.indexOf(field), 1); return remFields; }) ) ) ) .subscribe()