interval
и timer
могут использоваться для генерации цикла, который выполняется с частотой, не зависящей от времени, которое требуется для фактического опроса вашего сервера. Основываясь на описании «ожидаемого результата», похоже, что вы хотите частоту, на которую будет влиять период времени, необходимый для фактического опроса вашего сервера. Я думаю о вашем сценарии использования, как следующий (синхронный) цикл:
delay(3) // synchronously wait 3 seconds
while (!stopped) {
pollServer() // synchronously poll server; may take N seconds
delay(10) // synchronously wait 10 seconds
}
Я бы использовал repeatWhen
, чтобы построить вышеупомянутый цикл в эпопее. repeatWhen
облегчает запуск 10-секундной задержки только после завершения «итерации цикла». Вы просто задерживаете полное событие в наблюдаемых уведомлениях:
export const epic = action$ =>
action$.pipe(
ofType(BEGIN_PENDING_ACTIONS),
exhaustMap(action => // ignore actions while the loop is already running
of(action).pipe( // re-pipe so we can attach `takeUntil` to stop running the loop
delay(3000), // this is the initial delay
mergeMap(() =>
from(getDb()).pipe( // this is the start of the loop iteration
mergeMap(db => ...), // this is where you poll the server and emit Redux actions
repeatWhen(complete$ =>
complete$.pipe(
delay(10000), // on complete, wait 10 seconds, then repeat!
)
),
)
),
takeUntil(action$.pipe( // stop on end
ofType(END_PENDING_ACTIONS)
)),
)
),
)
Обратите внимание, что в приведенном выше примере repeatWhen
просто повторно подпишется на from(getDb())
. Значение db
всегда будет кэшированным значением из первой итерации. Если вам нужно повторно выполнять getDb()
на каждой итерации, тогда замените defer(() => from(getDb()))
.