Search code examples
angularngrxngrx-effects

NgRx Effects; Dispatching an Action from CatchError, while also returning the Error itself


I have an effect which catches the HttpErrorResponse, but since there's also a global error handler, I dont want to catch the error, I want to tap it.

The .catchError should both return the Error for the Interceptor, as well as dispatch the addItemFailure action

addItem$ = createEffect((): Observable<Action> => {
  return this.action$.pipe(
    ofType(ItemActions.addItem),
    exhaustMap((action) => {
      return this.apiClient.addItem(action.itemModel).pipe(
        map((response) => ItemActions.addItemSuccess({ response })),
        catchError((exception: HttpErrorResponse) => {
          return throwError(() => exception);
          return of(ItemActions.addItemFailure({ exception }));
        }),
      );
    }),
  );
});

Above of course does not work because of the double return, but it shows what I'm trying to achieve. Using one of them works, but I need them both to work.

I've tried:

catchError((exception: HttpErrorResponse) => {
  this.store.dispatch(ItemActions.addItemFailure({ exception }));
  return throwError(() => exception);
}),

or

catchError((exception: HttpErrorResponse) => {
  return throwError(() => {
    this.store.dispatch(ItemActions.addItemFailure({ exception }));
    return exception;
  });
})

But that doesn't work somehow.


Solution

  • Got it working with a little help from @ali-ataf:

    catchError((exception: HttpErrorResponse) => {
      of(EMPTY).pipe(
        tap(() => this.store.dispatch(ItemActions.addItemFailure({ exception }))),
        switchMap(() => throwError(() => exception)),
      )
    )
    

    Full Effect now looks like:

    addItem$ = createEffect((): Observable<Action> => {
      return this.action$.pipe(
        ofType(ItemActions.addItem),
        exhaustMap((action) => {
          return this.apiClient.addItem(action.itemModel).pipe(
            map((response) => ItemActions.addItemSuccess({ response })),
            catchError((exception: HttpErrorResponse) => {
              of(EMPTY).pipe(
                tap(() => this.store.dispatch(ItemActions.addItemFailure({ exception }))),
                switchMap(() => throwError(() => exception)),
              ),
            }),
          );
        }),
      );
    });