webentwicklung-frage-antwort-db.com.de

redux-observable - Sende mehrere Redux-Aktionen in einem einzigen Epos

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?

31
dotintegral

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.

33
paulpdaniels

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}; 
        }),
    );
});
1
Qiang