I found on the web that ErrorHandler can catch all errors as client-side errors and also httpErrorResponse
errors.
But in my situation, I can catch only client-side errors in GlobalErrorHandlerService, the other one httpErrorResponse
can't be caught.
What did I do wrong?
My app-module:
providers: [
{ provide: HTTP_INTERCEPTORS, useClass: MainInterceptorService, multi: true },
{ provide: ErrorHandler, useClass: GlobalErrorHandlerService },
],
bootstrap: [AppComponent]
})
export class AppModule { }
My GlobalErrorHandler:
import {ErrorHandler, Injectable} from '@angular/core';
import {HttpErrorResponse} from "@angular/common/http";
@Injectable({
providedIn: 'root'
})
export class GlobalErrorHandlerService implements ErrorHandler{
constructor() { }
handleError(error: any): void {
console.log("Handler work")
if (error instanceof HttpErrorResponse){
console.log("HttpErrorResponse")
} else {
console.log("Not httpErrorResponse")
}
}
}
My interceptor:
import { Injectable } from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/common/http";
import {catchError, Observable, throwError} from "rxjs";
import {error} from "@angular/compiler-cli/src/transformers/util";
@Injectable({
providedIn: 'root'
})
export class MainInterceptorService implements HttpInterceptor{
private httpError = {
status: 0,
message: ''
};
constructor() { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// req=req.clone({headers:req.headers.set("Auth","Bearer"+token)})
return next.handle(req).pipe(
catchError(
(error:HttpErrorResponse|Error)=>{
// server-side error
if (error instanceof HttpErrorResponse){
console.log("intercepter work")
return throwError(()=>new Error("Server side error"+error));
} else {
return throwError(()=>new Error("Client side error"+error))
}
}
)
)
}
}
My UserService
import { Injectable } from '@angular/core';
import {HttpClient, HttpErrorResponse} from "@angular/common/http";
import {User} from "../entity/user";
@Injectable({
providedIn: 'root'
})
export class UserService {
errors:any[]|undefined
private response:Response|undefined
constructor(private http:HttpClient) { }
readonly URL_BASE="http://****"
readonly URL_REGISTRATE="http://****"
registrUser(user:User):any {
return this.http.post<any>(this.URL_BASE+"/account/register", user)
}
loginUser(userName:string,password:string):any{
return this.http.post<any>(this.URL_BASE+"/account/signin",{userName,password})
}
}
If you explain the logic of ErrorHandler then it will be really a pleasure.
I think I now understand what's happening in your code:
MainInterceptorService
gets called. If you get a server-error, you convert the HttpErrorResponse
into a Error
-object.GlobalErrorHandlerService
gets hit, but since you already converted your error into an object of type Error
, it will no longer be recognized as HttpErrorResponse
and therefore it get's treated as client-side-error.catchError()
inside registrUser()
or loginUser()
, the GlobalErrorHandlerService
was not hit anymore for these methods, because the local catchError()
swallowed the errors (yet I could have rethrown the errors to trigger the GlobalErrorHandlerService
nevertheless ;-))Therefore our goal must be to refactor MainInterceptorService
in a way that it doesn't convert the original error-type to a different kind of object. This can be done as follows:
export class MainInterceptorService implements HttpInterceptor {
constructor() { }
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// req=req.clone({headers:req.headers.set("Auth","Bearer"+token)})
return next.handle(req).pipe(
catchError(
(err: HttpErrorResponse|Error)=>{
if (err instanceof HttpErrorResponse){
console.error('Server side error'+err);
} else {
console.error('Not a httpErrorResponse'+err);
}
return throwError(() => err);
}
)
);
}
}
Important:
MainInterceptorService
-code I showed above.HttpInterceptor
, since often times they are not related to a http-request.ErrorHandler
to handle client-side errors and HttpInterceptors
to handle errors related to http-requests.HttpInterceptor
could look like: Global ErrorHandler is not working after implementing catchError in ngrx effect