Я думаю, это должно сработать:
const newSubscription = new Subject();
const covidCases$ = interval(60 * 1000).pipe(
takeUntil(newSubscription),
repeat(),
switchMap(() =>
this.covidService.getCovidCases().pipe(
/* ... */
),
),
takeUntil(this.stopPolling),
shareReplay(1),
src$ => defer(() => (newSubscription.next(), src$))
);
Я заменил timer(1, 60 * 1000) + retry()
на interval(60 * 1000)
.
Я полагал, что для перезапуска таймера (interval()
) мы должны повторно подписаться на него. Но перед повторной подпиской мы должны сначала unsubscribed
от нее.
Вот что делают эти строки:
interval(60 * 1000).pipe(
takeUntil(newSubscription),
repeat(),
/* ... */
)
У нас есть таймер, пока не сработает newSubscription
. Когда это произойдет, takeUntil
выдаст complete notification
, а затем отменит подписку на свой источник (в данном случае источник, созданный interval
).
repeat
перехватит это complete notification
и повторно подпишется на наблюдаемый источник (source = interval().pipe(takeUntil())
), что означает, что таймер перезапустится.
shareReplay(1)
гарантирует, что новый подписчик получит последнее переданное значение.
Тогда очень важно разместить src$ => defer(() => (newSubscription.next(), src$))
после shareReplay
. Используя defer()
, мы можем определить момент прибытия нового подписчика.
Если бы вы поместили src$ => defer(() => (console.log('sub'), src$))
выше shareReplay(1)
, вы бы увидели, что sub
выполнено, зарегистрировано только один раз после создания первого подписчика. Поместив его под shareReplay(1)
, вы должны видеть это сообщение в журнале каждый раз, когда создается подписчик.
Вернемся к нашему примеру, когда новый подписчик зарегистрирован, newSubscription
будет излучать, что означает, что таймер будет перезапущен, но поскольку мы также используем repeat
, полное уведомление не будет передано shareReplay
, если только не отправит stopPolling
.
StackBlitz demo.
person
Andrei Gătej
schedule
07.06.2020
shareReplay(1)
? Это потому, что вы хотите перезапускать таймер при каждой подписке? - person martin   schedule 07.06.2020