I found in 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, other one httpErrorResponse can't be caught. What 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 intercepter:
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 a logic of ErrorHandler then i will be really pleasure.
CodePudding user response:
I think I now understand what's happening in your code:
- First your
MainInterceptorService
gets called. If you get a server-error, you convert theHttpErrorResponse
into aError
-object. - Second, your
GlobalErrorHandlerService
gets hit, but since you already converted your error into an object of typeError
, it will no longer be recognized asHttpErrorResponse
and therefore it get's treated as client-side-error. - What I also noticed: When I added a
catchError()
insideregistrUser()
orloginUser()
, theGlobalErrorHandlerService
was not hit anymore for these methods, because the localcatchError()
swallowed the errors (yet I could have rethrown the errors to trigger theGlobalErrorHandlerService
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:
- You can actually forget about the code-suggestion I made in my previous answer. Just leave everything as it is apart from the
MainInterceptorService
-code I showed above. - Be aware that client-side errors might not enter the
HttpInterceptor
, since often times they are not related to a http-request. - You basically use
ErrorHandler
to handle client-side errors andHttpInterceptors
to handle errors related to http-requests. - Under the following link you can find an example on what an error-related
HttpInterceptor
could look like: Global ErrorHandler is not working after implementing catchError in ngrx effect