Home > Net >  What need to do that ErrorHandler works correctly?
What need to do that ErrorHandler works correctly?

Time:12-31

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 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
  • Related