Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

rxjs - redux-observable - dispatch multiple redux actions in a single epic

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?

question from:https://stackoverflow.com/questions/40886655/redux-observable-dispatch-multiple-redux-actions-in-a-single-epic

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There is no requirement that you make a one-to-one in/out ratio. So you can emit multiple actions using mergeMap (aka flatMap) if you need to:

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

Note that any Rx operator that accepts an Observable also can accept a Promise, Array, or Iterable; consuming them as-if they were streams. So we could use an array instead for the same effect:

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

Which one you use depends on your personal style preferences and use case.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...