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 шт):
Коллеги из англоязычного домена подсказали, что нужно просто кешировать весь 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