infamousbazooka
infamousbazooka

Reputation: 19

NGRX Effects breaks app on error, how to handle errors?

I am using NGRX effects in my app. When it fails it seems to break the stream.

@Effect()
createUser$: Observable<Action> = _action$.ofType(fromUser.CREATE_NEW_USER_ACTION)
  .pipe(
    mergeMap((action: fromUser.CreateNewUserAction) =>
      this._tokenService.post('users', action.payload)
        .pipe(
          map(response => {
            this._router.navigate(
              ["dashboard", "users", "view"],
              { queryParams: { id: response.json().message.id } });
            return new fromUser.CreateNewUserCompleteAction(response.json().message);
          },
            catchError(error =>
              of(new fromUser.CreateNewUserFailedAction(error.json().message))
            )
          )
        )
    )
  );

The error action is never triggered, I tried logging.

Upvotes: 0

Views: 1888

Answers (2)

LeOn - Han Li
LeOn - Han Li

Reputation: 10194

Looks like your parentheses are not correctly placed inside the 2nd pipe function. The map and the catchError should be in parallel inside the pipe. In your code, the catchError function is inside map.

@Effect()
createUser$: Observable<Action> = _action$.ofType(fromUser.CREATE_NEW_USER_ACTION)
  .pipe(
    mergeMap((action: fromUser.CreateNewUserAction) =>
      this._tokenService.post('users', action.payload)
        .pipe(
          map(response => {
            this._router.navigate(
              ["dashboard", "users", "view"],
              { queryParams: { id: response.json().message.id } });
            return new fromUser.CreateNewUserCompleteAction(response.json().message);
          }),
          catchError(error =>
            of(new fromUser.CreateNewUserFailedAction(error.json().message))
          )
        )
    )
  );

BTW, this is a good practice placing the catchError with the http request rather than put in in the outer pipe stream which would potentially stop the action$ observable and no future actions will be received by the NGRX Framework.

Upvotes: 0

Joel Richman
Joel Richman

Reputation: 1934

What is your tokenService returning? It might be handling any errors from the API call internally. CatchError should work as long as your API call is not burying the error event. If that is the case you may need to throw the error from that service using Observable.throw().

I typically format my effects more like this for readability.

@Effect() updateUser$: Observable<Action>;

constructor(action$: Actions, tokenService: TokenService) {
this.updateUser$ = action$.ofType(fromUser.UPDATE_USER_ACTION)
.pipe(
    mergeMap((action: fromUser.UpdateUserAction) => 
        tokenService.patch(`users/${this.user.id}`, action.payload)
           .pipe(
              map(response => {
                 this._router.navigate(
                    ["dashboard", "users", "view"], 
                    { queryParams: { id: response.json().message.id } });
                 return new fromUser.UpdateUserCompleteAction(response.json().message); 
              },
              catchError(error => 
                 of(new fromUser.UpdateUserFailedAction(error.json().message))
              )
           )
        )
    )
);
}

This code looks like it should work. Take a look at your TokenService.

Upvotes: 1

Related Questions