45

I'm looking for way of dispatching multiple redux actions in a single Epic of redux-observable middleware.

Let's assume I have following Epic. Everytime when SEARCH event happens, Epic loads data from backend and dispatches RESULTS_LOADED action.

searchEpic = (action$) => 
    action$
    .ofType('SEARCH')
    .mergeMap(
        Observable
        .fromPromise(searchPromise)
        .map((data) => {
            return {
                type: 'RESULTS_LOADED',
                results: data
            }
        })
    )

Now, let's assume that I need dispatch additional action when the searchPromise is resolved.

The simplest way of doing so seems to have a second epic that will listen to RESULTS_LOADED and dispatch the second action. Like so:

resultsLoadedEpic = (action$) => 
    action$
    .ofType('RESULTS_LOADED')
    .map(({results} => {
         return {
             type: 'MY_OTHER_ACTION',
             results
         } 
    })

In this simple example it's quite easy. But when Epics grow, I tend to find myself having a lot of redux actions which sole purpose is to trigger other actions. Additionally, some of the rxjs code needs to be repeated. I find this a bit ugly.

So, my question: Is there a way to dispatch multiple redux actions in a single Epic?

4

2 回答 2

57

没有要求您进行一对一的输入/输出比率。因此,如果需要,您可以使用mergeMap(aka )发出多个操作:flatMap

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))
        ))
    )

请注意,任何接受 Observable 的 Rx 运算符也可以接受 Promise、Array 或 Iterable;消费它们,就好像它们是溪流一样。所以我们可以用一个数组来代替同样的效果:

.mergeMap((data) => [loaded(data), otherAction(data)])

您使用哪一种取决于您的个人风格偏好和用例。

于 2016-11-30T18:28:09.183 回答
2

或者也许你有三个动作,

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}; 
        }),
    );
});
于 2018-10-17T00:45:45.313 回答