От redux-observable
Epics в redux-observable — это RxJS-пайплайны над action stream. Самая распространённая форма — “отфильтровать по типу, сделать асинхронную штуку, эмитнуть результирующий action” — напрямую ложится на обработчик Triggery. Всё, что комбинирует несколько потоков реактивно (combineLatest, withLatestFrom) — это место, где pull-only модель Triggery и push-only модель RxJS начинают расходиться.
Соответствие ментальных моделей
Заголовок раздела «Соответствие ментальных моделей»| redux-observable / RxJS | Triggery |
|---|---|
Фильтр ofType('foo') | events: ['foo'] |
ofType('foo', 'bar') | events: ['foo', 'bar'] |
debounceTime(ms) на источнике | actions.debounce(ms).out?.(p) для выходов; вручную для гейтинга входов |
throttleTime(ms) | actions.throttle(ms).out?.(p) |
switchMap | concurrency: 'take-latest' (по умолчанию) |
mergeMap | concurrency: 'take-every' |
exhaustMap | concurrency: 'exhaust' |
concatMap | concurrency: 'queue' |
map(action => …) эмит action’а | actions.someAction?.(…) |
withLatestFrom(state$, sel) | conditions.someName, зарегистрированное через useReduxCondition |
combineLatest([a$, b$, c$]) | Нет прямого соответствия — см. ниже |
takeUntil(stop$) | Проверки signal.aborted в async handler |
Паттерн 1 — ofType + switchMap
Заголовок раздела «Паттерн 1 — ofType + switchMap»switchMap = take-latest. Семантика та же: новый вход отменяет предыдущую in-flight задачу.
Паттерн 2 — debounceTime на входе
Заголовок раздела «Паттерн 2 — debounceTime на входе»Triggery не гейтит входы с помощью debounce — конвенция в том, чтобы гейтить выход:
Реактор на другой стороне (useAction(trigger, 'runSearch', q => /* fetch */)) получает только последний вызов в пределах окна.
Паттерн 3 — withLatestFrom
Заголовок раздела «Паттерн 3 — withLatestFrom»Что не ложится чисто
Заголовок раздела «Что не ложится чисто»combineLatestнескольких потоков. Триггеры реагируют на одно событие за раз и подтягивают условия лениво — у них нет “запускайся, когда любой из этих потоков эмитнет”. Либо выбирай один как событие триггера, а остальные трактуй как условия, либо оставляй этот кусок как epic / RxJS-пайплайн и зовиfireEventизsubscribe.- Multicasting через
shareReplay. У hot/cold-семантики RxJS нет аналога в Triggery; если они нужны — оставь RxJS. - Операторы backpressure (
bufferTime,windowToggle). Планировщик Triggery батчит микрозадачи на тик, но не реализует backpressure-инструментарий RxJS.
Когда оставить RxJS
Заголовок раздела «Когда оставить RxJS»Оставляй RxJS для по-настоящему stream-heavy частей: анимационные пайплайны, сложная многосторонняя синхронизация, всё, где combineLatest / merge / partition делают реальную работу. Две библиотеки нормально сосуществуют — обработчик триггера может подписаться на одноразовый observable, а epic может dispatch-ить action, на который Triggery как раз слушает.