NGRX effect pipe not reached after exception in service

Viewed 98

I ran into a situation where I don't understand what I need to do to do this the correct way.

I'm using NGRX effects to handle sending http requests via separate services, so far so normal. Until now basically the only situation where I'd have an exception thrown by these is in the respective API the request is sent to and that is handled correctly by a catchError block inside whichever higher order observable I'm using in that effect.

Now I tried implementing a custom library (that I also wrote). In this library I'm doing some validation before actually sending the request. When I throw an error though, the pipe on the service call inside the effect is never reached (and thus not the catchError).
Doesn't matter that it is an external library, but that is just how I stumbled across this.

From stepping through with the debugger I can see that NGRX is apparently swallowing the error at some point and it is printed to the console, but I don't get it back to be able to show it to the user.

I reduced it to a small stackblitz where I just dispatch an action upon button press, the effect than uses switchMap to call a simple service function that throws an exception.
https://stackblitz.com/edit/angular-ivy-un8qem?file=src/app/app.component.html

The effect looks like this:

  callService$ = createEffect(() =>
    this.actions$.pipe(
      ofType(customActions.callService),
      switchMap(() =>
        this.customService.raiseException().pipe(
          // This pipe is never reached
          tap(() => console.log('callService$:raiseException.pipe')),
          map((msg) => customActions.callServiceSuccess({ msg })),
          catchError((err) => of(customActions.callServiceFail({ err })))
        )
      )
    )
  );

This is the service function:

  raiseException(): Observable<string> {
    if (1 == 1) throw new Error('Oh no, something went wrong!');

    return of('No exception!');
  }

If I understood the debugging correctly the exception is caught internally by NGRX in a subscription.

How can I actually get the exception back to the effect? Currently it will not continue at all, neither success nor fail.

1 Answers

Thanks to Zerotwelve in the comments I figured the kind of obvious way of doing this is returning the error as observable like this:

  raiseException(): Observable<string> {
    try {
      this.test(1);
    } catch (e) {
      return throwError(() => e);
    }

    return of('No exception!');
  }

  private test(x: number) {
    if (x == 1) throw new Error('Oh no, something went wrong!');
  }
Related