dispatch multiple actions in one effect dispatch multiple actions in one effect angular angular

dispatch multiple actions in one effect


@Effect()loadInitConfig$ = this.actions$    .ofType(layout.ActionTypes.LOAD_INIT_CONFIGURATION)    .map<Action, void>(toPayload)    .switchMap(() =>        this.settingsService            .loadInitConfiguration()            .mergeMap((data: any) => [                new layout.LoadInitConfigurationCompleteAction(data.settings),                new meetup.LoadInitGeolocationCompleteAction(data.geolocation)            ])            .catch(error =>                Observable.of(                    new layout.LoadInitConfigurationFailAction({                        error                    })                )            )    );


You can use switchMap and Observable.of.

 @Effect({ dispatch: true }) action$ = this.actions$    .ofType(CoreActionTypes.MY_ACTION)    .switchMap(() => Observable.of(        // subscribers will be notified        {type: 'ACTION_ONE'} ,        // subscribers will be notified (again ...)        {type: 'ACTION_TWO'}    ))    .catch(() => Observable.of({      type: CoreActionTypes.MY_ACTION_FAILED    }));

Performance matters :

Instead of dispatching many actions that will trigger all the subscribers as many times as you dispatch, you may want to take a look into redux-batched-actions.

This allows you to warn your subscribers only when all of those multiple actions have been applied to the store.

For example :

@Effect({ dispatch: true }) action$ = this.actions$    .ofType(CoreActionTypes.MY_ACTION)    // subscribers will be notified only once, no matter how many actions you have    // not between every action    .map(() => batchActions([        doThing(),        doOther()    ]))    .catch(() => Observable.of({      type: CoreActionTypes.MY_ACTION_FAILED    }));


If anyone wonders how to mix plain actions with ones from Observables.

I was stuck with same task, but small difference: I needed to dispatch two actions, with second one after API call, which made it an Observable. Something like:

  1. action1 is just an action: {type: 'ACTION_ONE'}
  2. action2 is API call mapped to action: Observable<{type: 'ACTION_TWO'}>

Following code solved my issue:

@Effect() action$ = this.actions$.pipe(    ofType(CoreActionTypes.MY_ACTION),    mergeMap(res =>        // in order to dispatch actions in provided order        concat(            of(action1),            action2        )    ),    catchError(() => Observable.of({        type: CoreActionTypes.MY_ACTION_FAILED    })));

concat doc's