Tengo el siguiente código:
this.currency$ = combineLatest([ this.currency.valueChanges, // Currency ID Form Control (selected currency id) this.currencies$, // A list of currencies, that is loaded from backend ]).pipe( map((result: [number, Currency[]]) => { // todo: optimize - do not loop over all, stop when found let currencyName = ''; if (result[1]) { result[1].forEach((currency: Currency) => { if (currency.id === this.currency.value) { currencyName = currency.name; } }); } return currencyName; }) ); El problema es que cuando me suscribo en la plantilla a la moneda$ observable, uso el | async tubería | async : el cálculo (determinación del nombre de la moneda) se realiza dos veces.
¿Cuál es una buena solución, calcularlo solo una vez y en cada suscripción, emitir un nombre de moneda ya calculado? Por supuesto, podría agregar una variable de componente y conservar el nombre allí, pero me gustaría usar observables, por lo que el componente no debería tener su propio estado...
Puede evitar esto usando el operador shareReplay https://www.learnrxjs.io/learn-rxjs/operators/multicasting/sharereplay para compartir la fuente y el cálculo se realizará solo una vez
import { map, shareReplay } from 'rxjs/operators'; ... this.currency$ = combineLatest([ this.currency.valueChanges, // Currency ID Form Control (selected currency id) this.currencies$, // A list of currencies, that is loaded from backend ]).pipe( map((result: [number, Currency[]]) => { // todo: optimize - do not loop over all, stop when found let currencyName = ''; if (result[1]) { result[1].forEach((currency: Currency) => { if (currency.id === this.currency.value) { currencyName = currency.name; } }); } return currencyName; }), shareReplay() // here );por otro lado, evite usar múltiples tuberías asíncronas en su plantilla, puede usar un contenedor ng para establecer el valor del resultado de su tubería asíncrona en una variable y usarlo en todas partes en su plantilla
<ng-container *ngIf="currency$ | async as curency"> // use currency here </ng-container>