angulartypescriptangular-routingangular6angular-errorhandler

Http Error Handling in Angular 6


I, am trying to handle the http error using the below class in angular 6. I got a 401 unAuthorized status from server. But however I, don't see the console error message.

HttpErrorsHandler.ts file

import { ErrorHandler, Injectable} from '@angular/core';
    @Injectable()
    export class HttpErrorsHandler implements ErrorHandler {
      handleError(error: Error) {
         // Do whatever you like with the error (send it to the server?)
         // And log it to the console
         console.error('It happens: ', error);
      }
    }

http error

app.module.ts file

providers: [{provide: ErrorHandler, useClass: HttpErrorsHandler}],

HttpCallFile

import { Injectable , Component} from '@angular/core';
import { HttpClient, HttpHeaders } from "@angular/common/http";
import { Observable } from 'rxjs';
import {AuthServiceJwt} from '../Common/sevice.auth.component';

@Injectable()
export class GenericHttpClientService {
    private readonly baseUrl : string = "**********";


    constructor(private httpClientModule: HttpClient , private authServiceJwt : AuthServiceJwt)  {
    }

    public GenericHttpPost<T>(_postViewModel: T , destinationUrl : string): Observable<T> {
        const headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8')
            .set('Authorization',`Bearer ${this.authServiceJwt.getToken}`);
        return this.httpClientModule.post<T>(this.baseUrl + destinationUrl, _postViewModel, { headers });
    }

    // This method is to post Data and Get Response Data in two different type
    public GenericHttpPostAndResponse<T,TE>(postViewModel: TE, destinationUrl: string): Observable<T> {
        const headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8')
            .set('Authorization',`Bearer ${this.authServiceJwt.getToken}`);
        return this.httpClientModule.post<T>(this.baseUrl + destinationUrl, postViewModel, { headers });
    }

    // This method is to post Data and Get Response Data in two different type without JWT Token
    public GenericHttpPostWithOutToken<T,TE>(postViewModel: TE, destinationUrl: string): Observable<T> {
        const headers = new HttpHeaders().set('Content-Type', 'application/json; charset=utf-8');
        return this.httpClientModule.post<T>(this.baseUrl + destinationUrl, postViewModel, { headers });
    }

    public GenericHttpGet<T>(destinationUrl: string): Observable<T> {
        const headers = new HttpHeaders().set('Content-Type', 'application/json')
            .set('Authorization',`Bearer ${this.authServiceJwt.getToken}`);
        return this.httpClientModule.get<T>(this.baseUrl + destinationUrl, { headers });
    }

    public GenericHttpDelete<T>(destinationUrl: string): Observable<T> {
        const headers = new HttpHeaders().set('Content-Type', 'application/json')
            .set('Authorization',`Bearer ${this.authServiceJwt.getToken}`);
        return this.httpClientModule.delete<T>(this.baseUrl + destinationUrl, { headers });
    }
}

admin.user.component.ts file

private getUsersHttpCall(): void {
    this.spinnerProgress = true;
    this.genericHttpService.GenericHttpGet<GenericResponseObject<UserViewModel[]>>(this.getAdminUserUrl).subscribe(data => {
      if (data.isSuccess) {
        this.genericResponseObject.data = data.data;
        this.dataSource = this.genericResponseObject.data
        this.spinnerProgress = false;
      }

    }, error => {
      console.log(error);
      this.spinnerProgress = false;
    });
  }

Solution

  • For XHR request you should use an Interceptor

    This is the one I use to add JWT to headers and to handle some response errors:

    import {Injectable} from '@angular/core';
    import {
      HttpRequest,
      HttpHandler,
      HttpEvent,
      HttpInterceptor, HttpErrorResponse
    } from '@angular/common/http';
    import {AuthService} from '../service/auth.service';
    import {Observable, of} from 'rxjs';
    import {Router} from "@angular/router";
    import {catchError} from "rxjs/internal/operators";
    
    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
    
      constructor(public auth: AuthService, private router: Router) {
      }
    
    
      /**
       * intercept all XHR request
       * @param request
       * @param next
       * @returns {Observable<A>}
       */
      intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    
        if (localStorage.getItem('jwtToken')) {
          request = request.clone({
            setHeaders: {
              Authorization: 'Bearer ' + localStorage.getItem('jwtToken')
            }
          });
        }
    
        /**
         * continues request execution
         */
        return next.handle(request).pipe(catchError((error, caught) => {
            //intercept the respons error and displace it to the console
            console.log(error);
            this.handleAuthError(error);
            return of(error);
          }) as any);
      }
    
    
      /**
       * manage errors
       * @param err
       * @returns {any}
       */
      private handleAuthError(err: HttpErrorResponse): Observable<any> {
        //handle your auth error or rethrow
        if (err.status === 401) {
          //navigate /delete cookies or whatever
          console.log('handled error ' + err.status);
          this.router.navigate([`/login`]);
          // if you've caught / handled the error, you don't want to rethrow it unless you also want downstream consumers to have to handle it as well.
          return of(err.message);
        }
        throw err;
      }
    }
    

    Don't forget to register you interceptor into app.module.ts like so:

    import { TokenInterceptor } from './auth/token.interceptor';
    
    @NgModule({
      declarations: [],
      imports: [],
      exports: [],
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          useClass: TokenInterceptor,
          multi: true,
        }
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }