Контекст: в ангуляре удобно связывать бекенд и сервисы с помощью RXJS стримов. Протягивать стримы до самых вьюх, где вьюха подписывается на стрим (с помощью async
pipe) и триггерит всю цепочку вызовов операторов. Преимущество этого подхода в том что вьюха сама отпишется от стрима когда будет “убита” при навигации на другую вьюху.
В RXJS есть оператор shareReplay
который я использую когда одни и те же данные с бекенда используются разными компонентами на клиенте. Этот оператор позволяет сделать 1 запрос и переиспользовать его результаты во всех потребителях.
В моем случае есть дашборд который обновляется каждые X секунд (это смоделировано в observable this.refreshInterval
), и где данные из 1 API используются в нескольких компонентах.
Код выглядит примерно так:
this.countersDto$ = combineLatest([this.userSelectedDealersSubject, this.refreshInterval]).pipe(
switchMap(([dealersIds, _]) => {
return this.dashboardApiService.getCounters({ dealers: dealersIds });
}),
shareReplay(1)
);
Проблема
когда пользователь уходит со страницы observalbe this.countersDto$
продолжает слать запросы к бекенду в интервале. Оказывается это известная проблема 1, 2 с оператором shareReplay
.
Решение
Чтобы потребители отписались от моего observable нужно передать дополнительный параметр в shareReplay
:
this.countersDto$ = combineLatest([this.userSelectedDealersSubject, this.refreshInterval]).pipe(
switchMap(([dealersIds, _]) => {
return this.dashboardApiService.getCounters({ dealers: dealersIds });
}),
shareReplay({
bufferSize: 1,
refCount: true
})
);