Между сагами (генераторами) и эпиками (наблюдаемыми) важно изменить то, как вы думаете о том, как события поступают в ваш код.
Генераторы удовлетворяют итератору и итерируемым протоколам, которые включают извлечение значения / события (в данном случае действия Redux) из источника и блокирование выполнения до тех пор, пока эти события не поступят.
Наблюдаемые значения pu sh, а не pull. Мы описываем и называем потоки интересующих нас событий, а затем подписываемся на них. Блокирующих вызовов нет, потому что весь наш код вызывается событиями, когда они происходят.
Этот код повторяет поведение в примере саги.
import { interval, timer } from 'rxjs';
import { withLatestFrom, mapTo, exhaustMap, takeUntil } from 'rxjs/operators';
import { ofType } from 'redux-observable';
const myEpic = (action$, state$) => {
// A stream of all the "cancel start" actions
const cancelStart$ = action$.pipe(ofType('CANCEL_START'));
// This observable will emit delayed start events that are not cancelled.
const delayedCancellableStarts$ = action$.pipe(
// When a start action occurs...
ofType('START'),
// Grab the latest start delay value from state...
withLatestFrom(state$, (_, { startDelay }) => startDelay),
exhaustMap(
// ...and emit an event after our delay, unless our cancel stream
// emits first, then do nothing until the next start event arrives.
// exhaustMap means we ignore all other start events while we handle
// this one.
(startDelay) => timer(startDelay).pipe(takeUntil(cancelStart$))
)
);
// On subscribe, emit a tick action every 10ms
const tick$ = interval(10).pipe(mapTo({ type: 'TICK' }));
// On subscribe, emit only STOP or RESET actions
const stopTick$ = action$.pipe(ofType('STOP', 'RESET'));
// When a start event arrives, start ticking until we get a message to
// stop. Ignore all start events until we stop ticking.
return delayedCancellableStarts$.pipe(
exhaustMap(() => tick$.pipe(takeUntil(stopTick$)))
);
};
Важно даже если мы создаем и называем эти наблюдаемые потоки, их поведение лениво - ни один из них не «активируется» до тех пор, пока не будет подписан, и это происходит, когда вы предоставляете эту функцию epi c промежуточному программному обеспечению redux-observable
.