1
votes

I'm having trouble dispatching multiple actions in the following effect:

    @Effect()
    someEffect$ = this.actions$.pipe(
      ofType(someAction: Actions),
      mergeMap(
        (action)=>{
          return this.authService.getProfile(action.payload.authInfo).pipe(
              map((response: any) => {

                  if (response.isErrorResponse) {
                    return new HeaderActions.AuthFail(response);
                  } else {

                 //here i'd like to return multiple actions
                    return [
                      new HeaderActions.FetchMPInfoSuccess(this.fetchMpInfoSuccesState(getMpProfileResponse)),
                      new HeaderActions.GetAccountStates(true)
                  ]
                  }
              }),
              catchError((error:HttpErrorResponse )=>{
                return of(new HeaderActions.AuthFail(response));
              })
            );
        }
      )
    );

I've tried adding an array of actions, in the return block, but that's giving an error that im not sending a valid action, any idea what i'm doing wrong?

2
that's not working ← See "It's not working" is not helpful, specifically point 3 and 4. - Igor
1. if (response.isErrorResponse) ← that should not have to be checked here, make sure you are building restful APIs that return error status codes on failure. 2. The additional actions you want to execute should not be started in map, use switchMap instead and you can execute the actions simultaneously using forkJoin - Igor
can you provide that as an answer so I can give it a try? - Kode_12
You can take the parts of my comment and search on them and try to alter your code accordingly. - Igor

2 Answers

4
votes

You can use switchMap instead of mergeMap. Then use flatMap or switchMap instead of map.

The code should be like this:

@Effect()
someEffect$ = this.actions$.pipe(
  ofType(someAction: Actions),
  switchMap(
    (action)=>{
      return this.authService.getProfile(action.payload.authInfo).pipe(
          flatMap((response: any) => {

              if (response.isErrorResponse) {
                return new HeaderActions.AuthFail(response);
              } else {

             //here i'd like to return multiple actions
                return [
                  new HeaderActions.FetchMPInfoSuccess(this.fetchMpInfoSuccesState(getMpProfileResponse)),
                  new HeaderActions.GetAccountStates(true)
              ]
              }
          }),
          catchError((error:HttpErrorResponse )=>{
            return of(new HeaderActions.AuthFail(response));
          })
        );
    }
  )
);

To access data in your child component you can use this approach with @Input() set stuff:

@Input() set(data: any) {
if (data) { console.log(data) }}

The data in html will be there always.

Map modifies each item emitted by a source Observable and emits the modified item.

FlatMap, SwitchMap also applies a function on each emitted item but instead of returning the modified item, it returns the Observable itself which can emit data again.

FlatMap merge items emitted by multiple Observables and returns a single Observable.

SwitchMap is a bit different from FlatMap. SwitchMap unsubscribes from the previous source Observable whenever new item started emitting, thus always emitting the items from current Observable.

If you would like to know more about rxjs operators, please have a look here.

-1
votes

Try:


@Effect()
    someEffect$ = this.actions$.pipe(
      ofType(someAction: Actions),
      switchMap(
        (action)=>{
          return this.authService.getProfile(action.payload.authInfo).pipe(
              map((response: any) => {

                  if (response.isErrorResponse) {
                    return [new HeaderActions.AuthFail(response)];
                  } else {

                 //here i'd like to return multiple actions
                    return [
                      new HeaderActions.FetchMPInfoSuccess(this.fetchMpInfoSuccesState(getMpProfileResponse)),
                      new HeaderActions.GetAccountStates(true)
                  ]
                  }
              }),
              catchError((error:HttpErrorResponse )=>{
                return of(new HeaderActions.AuthFail(response));
              })
            );
        }
      )
    );

So basically What I did was, instead of using a mergeMap before the service call, I swapped it back to simple switchMap.

Reason why I changed it from mergeMap was: you are only returning value from a single stream.