Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling errors in NGXS (angular) with global error handler

Tags:

angular

ngxs

I'd like to handle errors in NGXS in two ways. The first way is handling an error on the store dispatch in a component. The second way is a global angular error handler as a fallback for when the error is unhandled (not handled by first way).

But the problem is that the global error handler is always called by NGRX when there is an error in an action handler.

So given this code in the component:

this.store.dispatch(new FetchAction())
   .subscribe( error: () => console.log('fetch error occured'))

this action handler:

fetch() {
   return this.http.get('..');
}

and this global error handler:

export class GlobalErrorHandler extends ErrorHandler {
   handleError(err: any) {
      console.log('unexpected error occured');
   }
}

There would be two error messages in the console. One from the subscribe of the dispatch and one from the global error handler because there was an error in the action handler.

Now I could catch errors in the action handler but that would be the wrong place to do so because the action handler shouldn't know that an error from this action is handled in a component.

I made a stackblitz which shows two errors in the console when clicking the button: https://stackblitz.com/edit/ngxs-error-throw-r42fkb?file=src/app/app.component.ts

like image 940
cmart Avatar asked Nov 17 '22 06:11

cmart


1 Answers

Use RxJS catchError operator to handle errors at low level:

This way, you caught the error so it won't call your global action handler.

this.store.dispatch(new FetchAction())
   .pipe(catchError(error => /* Do something specific with the error. */))
   .subscribe(() => { /* Do something with the success result. */ })

Let the error bubble up to the global action handler:

Nothing special here. Just ignore the error. Do this when you don't know what to do with the error.

this.store.dispatch(new FetchAction())
   .subscribe(() => { /* Do something with the success result. */ })

You can re-throw a more specific error if you want with throwError so you have more information when you will handle it at a higher level.

this.store.dispatch(new FetchAction())
   .pipe(catchError(error => throwError(new Error('Some specific error.'))))
   .subscribe(() => { /* Do something with the success result. */ })
like image 184
Maxime Gélinas Avatar answered Jun 07 '23 14:06

Maxime Gélinas