Synchronized при вызове angular-сервиса

В Angular 15 приложении есть несколько компонентов, которые одновременно вызывают метод сервиса (который вызывает rest бакенда). Сам сервис сразу проверяет, есть ли уже требуемые данные во внутреннем кеше, и если нету - то вызывает ендпоинт и кеширует результат. Выглядит это таким образом:

export class CryptoMarketService implements MarketService {
   private _activeOrdersCache: Cache<Array<Order>> = new Cache<Array<Order>>();
   ...
    getActiveOrders(): Observable<Array<Order>> {   // тут нужен synchronized метода
       if (this._activeOrdersCache.hasCache()) {
           return of(this._activeOrdersCache.get());
       }

       return this.httpClient.get('/market/orders/active')
        .pipe(
            map((res: any) => {
                return Order.fromJsonArray(res);
            }),
            tap((activeOrders: Array<Order>) => {
                this._activeOrdersCache.set(activeOrders, 5, TimeUnit.MINUTES);
            })
        );
}

Проблема в том, что компоненты вызывают этот метод одновременно и, соответственно, оба сразу фактически вызывают бакенд ендпоинта, минуя кеш, после чего записываются в кеш. Подскажите, можно ли как-то синхронизировать этот метод, чтобы пока один поток обрабатывает метод второй ожидал и только потом заходил и получал данные уже с локального кеша?


Ответы (1 шт):

Автор решения: Alexander Kozlov

Коллеги из англоязычного домена подсказали, что нужно просто кешировать весь Observable и использовать shareReplay оператор:

...
private _activeOrdersCache: Cache<Observable<Array<Order>>> = new Cache<Observable<Array<Order>>>();
...
    getActiveOrders(): Observable<Array<Order>> {
    if (!this._activeOrdersCache.hasCache()) {
        const observable: Observable<Array<Order>> = this.httpClient.get('/orders/active', { params: httpParams })
               .pipe(
                   map((res: any) => {
                       return Order.fromJsonArray(res);
                   }),
                   shareReplay(1)
               );

        this._activeOrdersCache.set(observable, 5, TimeUnit.MINUTES);
    }

    return this._activeOrdersCache.get();
}

Подробнее тут: https://stackoverflow.com/questions/77638897/how-to-make-synchronized-method-in-angular-service

→ Ссылка