3

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.

fatihyildizhan
  • 8,614
  • 7
  • 64
  • 88

1 Answers1

2

I think I now understand what's happening in your code:

  • First your MainInterceptorService gets called. If you get a server-error, you convert the HttpErrorResponse into a Error-object.
  • Second, your 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.
  • What I also noticed: When I added a 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:

  • 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 and HttpInterceptors 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
kellermat
  • 2,859
  • 2
  • 4
  • 21
  • So your problem is solved now? Or do you still have any open questions concerning error-handling? – kellermat Dec 29 '22 at 14:39
  • Nope, look at my code in GlobalErrorHandler. I can't to get "Handler work" message when I'm getting server side HttpErrorResponse instance. – RobertcodeR Dec 30 '22 at 05:48
  • I don't know why, cause I implemented correctly and provided at AppModule. Hovewer he doesn't work and i can't to gather all errors together by that issue – RobertcodeR Dec 30 '22 at 05:50
  • OK, I now updated my answer. I tried your code in my own project and I think I found out what the problem was. – kellermat Dec 30 '22 at 11:55
  • Yes, you rescued me. All work but I change two files. I deleted the error in MainInterceptionService and added CatchError instead how you said before and second file which you showed above. Thank you for help. Congratulation with Happy New Year!!! – RobertcodeR Dec 30 '22 at 13:15
  • I'm glad I could help :-). Happy new year to you too :-). – kellermat Dec 30 '22 at 16:13