Расследование
В случае кода примера, который вы привели, первое, что нам нужно сделать, это сделать отступ и отформатировать код, чтобы было легче понять, что происходит.
const somethingEpic = action => {
const sampleFilteredStores = Observable.of([
{ type: 'FILTERED_STORES', store: 'a' },
{ type: 'FILTERED_STORES', store: 'b' }
]);
const filteredStores$ = action$.ofType('SEARCH_STORES')
.mapTo(
Observable.of(sampleFilteredStores)
.mergeAll()
);
return filteredStores$;
};
Как именно вы форматируете свой код, зависит от вас, но я лично нахожу что-то подобное этому гораздо более читабельному. Это поможет вам в отладке, а также существенно поможет будущим специалистам по сопровождению вашего кода понять ваши намерения.
картаКуда
Теперь я сразу вижу одну проблему: вы передаете Observable в mapTo
, что очень необычно для Rx. Это, конечно, не неправильно в 100% случаев, но в 99,99% и даже в 0,01% были бы гораздо более четкие способы показать желаемое намерение.
Observable.of
Копаясь дальше, я вижу два варианта использования Observable.of
.
Первое, что бросается в глаза, это то, что вы передаете Observable в Observable.of
: Observable.of(sampleFilteredStores)
Здесь применяется тот же совет, что и в mapTo
, это очень редко и не рекомендуется, потому что это создает Observable более высокого порядка без необходимости. Я вижу, что вы используете mergeAll()
, чтобы сгладить его, но это дает вам Observable, который в основном идентичен тому, что sampleFilteredStores
без косвенности.
Когда я копаю еще глубже, я замечаю еще одну тонкую, но важную вещь: вы передаете массив действий в Observable.of
. Это также очень подозрительно, потому что это означает, что вы создаете Observable, который просто генерирует массив из двух действий, а не испускает эти два действия последовательно напрямую. Если позже вы намеревались, вместо этого вам нужно было передать объекты непосредственно в качестве самих аргументов. Observable.of(action1, action2, action3, ...etc)
. Возможно, вы запутались, увидев, как кто-то использует Observable.from
для передачи массива, но это отличается от Observable.of
.
Первопричина
Объединив эти открытия, я теперь вижу, что этот эпос на самом деле испускает Observable, а не действия, поэтому вы получаете сообщение об ошибке от redux. Сам этот Observable на самом деле будет генерировать массив действий, поэтому, даже если вы сгладите этот Observable, вы все равно получите ту же ошибку.
Решение
Похоже, что предоставленный код, вероятно, придуман либо для упрощения вашего вопроса, либо для того, чтобы вы изучали Rx или наблюдаемый с редукцией. Но в этом конкретном случае я полагаю, что вы хотели прослушать SEARCH_STORES
и при получении последовательно отправить два действия типа FILTERED_STORES
с разными значениями store
.
Используя идиоматический Rx, это может выглядеть примерно так:
const somethingEpic = action => {
return action$.ofType('SEARCH_STORES')
.mergeMap(() => Observable.of(
{ type: 'FILTERED_STORES', store: 'a' },
{ type: 'FILTERED_STORES', store: 'b' }
))
};
Здесь мы используем mergeMap
, но так как Observable.of
мы выравниваем в испускаемых синхронно, мы могли бы также использовать switchMap
или concatMap
, они имели бы такой же суммарный эффект — но это не относится к Observables, которые испускают асинхронно! Поэтому обязательно изучите различные операторы стратегии выравнивания.
Эту цепочку можно описать так: всякий раз, когда мы получаем объект со свойством type
равно SEARCH_STORES
, сопоставляем его с Observable из двух объектов (FILTERED_STORES
действий), которые испускаются последовательно и синхронно.
Закрытие
Надеюсь, это поможет! Одна вещь, которую следует иметь в виду при изучении и использовании redux-observable, заключается в том, что почти полностью «просто RxJS» имеет дело с объектами, которые являются «действиями». Таким образом, нормальный идиоматический Rx является нормальным идиоматическим редукционно-наблюдаемым. То же самое с проблемами, с которыми вы можете столкнуться. Единственная реальная разница заключается в том, что redux-observable предоставляет единственный оператор ofType
в качестве сокращения для filter
(как описано в документах). Если в будущем у вас возникнут проблемы с Rx, возможно, вам будет полезно реорганизовать ваши примеры, чтобы использовать filter
, и сформулировать их независимо от наблюдаемых с избыточностью, поскольку сообщество Rx, очевидно, намного больше!
person
jayphelps
schedule
06.06.2017