Home > Back-end >  RxJs loop on a list of observables one by one
RxJs loop on a list of observables one by one

Time:01-11

I'm facing a problem that I can't solve because of my low RxJs experience. I explain to you. In my code below I have a request (createSOFromTransportTask) which is sent and it returns me a list of IDs.

This list is in a certain specific order (ofsExample = [35, 46, 54,..]). So I loop over this list to print labels, but they print in random order since my forEach loop sends the prints too quickly one after the other. So the server prints the labels according to the first come (example: [54, 35, 46,..])

async onGenerateShopOrders() {
    await this._printService.checkUserPrinterLocation();

    this._loading.show(this._transloco.translate('ecoOrder.MESSAGE.LOADING.SHOPORDERS'));

    let input = { ... };

    this._store.createSOFromTransportTask(input).pipe(
        finalize(() => this._loading.hide()),
        tap((ofs: string[]) => {
            if (ofs.length > 0) {
                let dialogRef: MatDialogRef<DialogInfoComponent> = this._dialog.open(DialogInfoComponent, {
                    disableClose: true
                });
                dialogRef.componentInstance.message = this._transloco.translate('ecoOrder.MESSAGE.SHOPORDERS.INFO', { ofs: ofs.join(';') });

                ofs.forEach((of: string) => {
                    // HERE, I need to send printLabels one by one
                    console.debug("Print OF :", of);
                    this._store.printLabels(of).subscribe();
                });
            }
        })
    ).subscribe({
        next: () => this.resetData()
    });
}

Does anyone have a solution to overcome this problem, it would be necessary to browse the list ofs and at each send wait for a return to launch the next one.

ofs.forEach((of: string) => {
    // HERE, I need to send printLabels one by one
    this._store.printLabels(of).subscribe();
});

I hope to have been precise in my request if you have any ideas I am a taker, Thank you.

CodePudding user response:

You can use concat() from RxJs, which prevents the next observable to be fired unless the current one is completed.

And with Array.map(), you can map the ofs array to an array of observables, then subscribe them all once

...

if (ofs.length > 0) {
    let dialogRef: MatDialogRef < DialogInfoComponent > = this._dialog.open(DialogInfoComponent, {
        disableClose: true
    });
    dialogRef.componentInstance.message = this._transloco.translate('ecoOrder.MESSAGE.SHOPORDERS.INFO', {
        ofs: ofs.join(';')
    });

    concat(...ofs.map(currentOf => this._store.printLabels(of))).subscribe()

}
...
  • Related