angularangular-cliangular-http-interceptorsangular-errorhandler

How to implement a global ErrorHandler along with an HttpInterceptor in Angular?


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.


Solution

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

    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: