Ich suche nach einer Möglichkeit, mehrere Redux-Aktionen in einem einzigen Epos von redux-observable
Middleware.
Nehmen wir an, ich folge Epic. Jedes Mal, wenn das Ereignis SEARCH
eintritt, lädt Epic Daten aus dem Backend und sendet RESULTS_LOADED
Aktion.
searchEpic = (action$) =>
action$
.ofType('SEARCH')
.mergeMap(
Observable
.fromPromise(searchPromise)
.map((data) => {
return {
type: 'RESULTS_LOADED',
results: data
}
})
)
Nehmen wir nun an, dass ich zusätzliche Aktionen ausführen muss, wenn das searchPromise
aufgelöst ist.
Die einfachste Art, dies zu tun, scheint ein zweites Epos zu haben, das RESULTS_LOADED
und die zweite Aktion auslösen. Wie so:
resultsLoadedEpic = (action$) =>
action$
.ofType('RESULTS_LOADED')
.map(({results} => {
return {
type: 'MY_OTHER_ACTION',
results
}
})
In diesem einfachen Beispiel ist es ganz einfach. Aber wenn Epics wachsen, neige ich dazu, viele Redux-Aktionen zu haben, deren einziger Zweck darin besteht, andere Aktionen auszulösen. Zusätzlich muss ein Teil des rxjs-Codes wiederholt werden. Ich finde das ein bisschen hässlich.
Meine Frage: Gibt es eine Möglichkeit, mehrere Redux-Aktionen in einem einzigen Epos auszuführen?
Es ist nicht erforderlich, dass Sie ein Eins-zu-Eins-In/Out-Verhältnis festlegen. Sie können also mit mergeMap
(aka flatMap
) mehrere Aktionen ausgeben, wenn Sie Folgendes benötigen:
const loaded = (results) => ({type: 'RESULTS_LOADED', results});
const otherAction = (results) => ({type: 'MY_OTHER_ACTION', results});
searchEpic = (action$) =>
action$
.ofType('SEARCH')
.mergeMap(
Observable
.fromPromise(searchPromise)
// Flattens this into two events on every search
.mergeMap((data) => Observable.of(
loaded(data),
otherAction(data))
))
)
Beachten Sie, dass jeder Rx-Operator, der eine Observable akzeptiert, auch eine Promise, ein Array oder eine Iterable akzeptieren kann. sie zu konsumieren, als ob sie Ströme wären. Wir könnten stattdessen ein Array für denselben Effekt verwenden:
.mergeMap((data) => [loaded(data), otherAction(data)])
Welches Sie verwenden, hängt von Ihren persönlichen Stilvorlieben und Ihrem Anwendungsfall ab.
Oder vielleicht haben Sie drei Aktionen,
API_REQUEST, API_RUNNING, API_SUCCESS,
searchEpic = (action$) =>
action$
.ofType('API_REQUEST')
.mergeMap((action) => {
return concat(
of({type: 'API_RUNNING'}),
Observable.fromPromise(searchPromise)
.map((data) => {
return {type: 'API_SUCCESS', data};
}),
);
});