Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Firing multiple actions on catch error

I am struggling to figure out how to fire multiple actions in a catch error handler in my epics.

I have successfully figured out how to fire multiple actions on a successful async call in my epics using the thunk-middleware. See below:

const editDomainsEpic = (action$) =>
  action$
    .ofType(EDIT_DOMAINS)
    .mergeMap((action) =>
      Rx.Observable.fromPromise(api.editDomains(action.payload))
        // Here we are using Redux thunk middleware to execute
        // a function instead of just dispatching an action
        // so that we can disptach two actions
        // ----------------- vvv
        .map((domain) => (dispatch) => {
          // Display Growl Notifications
          dispatch(
            displayGrowlNotification(
              MESSAGE_TYPES.SUCCESS,
              `${domain.name} was saved`
            )
          )
          // Fire Success Action
          dispatch({
            type: EDIT_DOMAINS_SUCCESS,
            payload: { domain }
          })
        })
        .catch((error) => Rx.Observable.of({
          type: EDIT_DOMAINS_ERROR,
          payload: { error }
        }))
        .takeUntil(action$.ofType(EDIT_DOMAINS_CANCEL))
    )

Can anyone guide me to how I can have the catch return or fire two observable actions that will get dispatched similarly to how I did with the success?

like image 375
Adam Duro Avatar asked Feb 21 '17 07:02

Adam Duro


Video Answer


1 Answers

Observable.of() supports an arbitrary number of arguments and will emit them all sequentially one after the other, so to emit more than one action in your catch, you just add more arguments.

With that knowledge at hand, you can also use it to dispatch multiple actions for success instead of emitting a thunk and imperatively calling dispatch yourself.

const editDomainsEpic = (action$) =>
  action$
    .ofType(EDIT_DOMAINS)
    .mergeMap((action) =>
      Rx.Observable.fromPromise(api.editDomains(action.payload))
        .mergeMap((domain) => Rx.Observable.of(
          displayGrowlNotification(
            MESSAGE_TYPES.SUCCESS,
            `${domain.name} was saved`
          ), {
            type: EDIT_DOMAINS_SUCCESS,
            payload: { domain }
          }
        ))
        .catch((error) => Rx.Observable.of({
          type: EDIT_DOMAINS_ERROR,
          payload: { error }
        }, {
          type: ANOTHER_ONE,
          payload: 'something-else'
        }))
        .takeUntil(action$.ofType(EDIT_DOMAINS_CANCEL))
    )

This would be more idiomatic RxJS (and thus redux-observable) but it's not necessarily a requirement.

like image 91
jayphelps Avatar answered Sep 28 '22 04:09

jayphelps