Reputation: 1
In an Angular app, I implemented a custom error handler which shows an alert (Angular Material snackbar) and dispatches a ngrx action to hide a loading spinner.
Here is an error handler:
export class ErrorHandlerService extends ErrorHandler {
constructor(private snackbar: SnackbarService, private store: Store<AppState>) {
super();
}
override handleError(error: any): void {
super.handleError(error);
const msg =
error.rejection?.message ?? error.error?.message ?? error.message;
this.snackbar.openSnackBar(msg, true);
this.store.dispatch(loadingZero());
}
}
The reducer would listen to LOADING_ZERO action and set the counter to 0 (loading spinner is shown if the counter is more than zero, and hidden if it equals zero).
The root component subscribes to the selector and shows/hides the spinner respectively. I'm using ngx-spinner.
export class AppComponent implements OnInit, OnDestroy {
isLoading$ = this.store.select(isLoadingSelector);
_destroying$ = new Subject<boolean>();
constructor(
private spinner: NgxSpinnerService,
// ...
) {}
ngOnInit() {
this.isLoading$
.pipe(takeUntil(this._destroying$))
.subscribe((value) =>
value ? this.spinner.show() : this.spinner.hide(),
);
// ...
}
// ...
}
Here is the problem: an error in rendering a template leads to infinite loop. Other errors (like a failed HTTP request) do not. If I do not dispatch a ngrx action in the error handler, the error does not get looped as well.
I guess it has something to do with change detection, but still unable to figure it out.
Upvotes: 0
Views: 579
Reputation: 15505
I find that keeping a request counter is error-prone (as you can see here). A better solution would be to store the request state per entity, and combine all loading states into one. This can further be extended (if needed), and show different spinners based on which request is pending.
That being said, "an error in rendering a template leads to infinite loop" makes me think that the counter will be negative (or the stats will be off), and thus will show the spinner.
A solution would be to only dispatch the action if the error is a HTTP error, or you could also implement a HTTP Interceptor, which dispatches the action. This way, the error will only be dispatched for failing HTTP requests.
Upvotes: 0