Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dispatch multiple actions from effects: difference between different rxjs operators

I need to dispatch multiple actions from an ngrx effect once an http request is successful.

There are several ways that seem to work and some that don't, I can't understand what the difference is.

@Effect()
    loadUser = this.actions
        .pipe(
            ofType(campaignActions.type.LOAD_CAMPAIGN),
            map((action: userActions.LoadUserAction) => action.payload),
            switchMap((payload: { id: number }) =>
                this.s.getUser(payload.id)
                    .pipe(
                        switchMap((data) => {

                            return from([
                                new userActions.LoadUserSuccessAction(),
                                new userActions.SomethingElseSuccessAction()
                            ]);
                        }),
                        catchError(() => of(new userActions.LoadUserFailureAction()))
                    )
            )
        );

First of all, I can use switchMap or mergeMap. I believe the difference is that if this effect is triggered multiple times, any ongoing requests will be cancelled if I use switchMap and not if I use mergeMap.

In terms of dispatching multiple actions, all the following works:

  • return [action1, action2]
  • return from([action1, action2])
  • return of(action1, action2)

The following doesn't work:

  • return of([action1, action2]) --> Effect "UserEffects.loadUser" dispatched an invalid action: [object Object],[object Object]

What is the difference between all the first 3 options? What about mergeMap vs switchMap after the http request? Why doesn't the last option work?

like image 701
MartaGalve Avatar asked Jun 20 '18 04:06

MartaGalve


1 Answers

This question can be separated into few sections:

+) Difference between mergeMap and switchMap:

  • mergeMap = map + mergeAll. It maps a data stream to observable stream, and everytime the inner observable emits a value, the outer will collect and merge all emitted value into a new stream.

  • switchMap, very similar, but as you can tell it "switches", i.e. if the next inner observable emits a new value, the previous one gets canceled (one inner observable at a time).

+) Similarity between mergeMap and switchMap: They can both convert any stream-like object to an observable.

+) Difference between your code:

  • return [action1, action2] does indeed make switchMap(() => ...) similar to from([action1, action2]), i.e. create an observable from an array.

  • return from([action1, action2]), this is an inner observable that emits 2 actions, and switchMap merges those actions back to its stream.

  • return of(action1, action2) = from([action1, action2])

  • return of([action1, action2]), however, creates an observable that emits a single value, which is an array, and you cannot call store.dispatch(array_of_actions)

like image 79
Ngoc Nam Nguyen Avatar answered Nov 14 '22 01:11

Ngoc Nam Nguyen