ERROR HANDLING

  1. We can use error handler that will alert the user of the error
           
                import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { Observable, throwError } from 'rxjs';
    import { map, retry, catchError } from 'rxjs/operators'
    
    @Injectable({
      providedIn: 'root'
    })
    export class AppServiceService {
      base_Url = 'https://api.chucknorris.io/jokes';
    
      constructor(private  http: HttpClient) { }
    
      getJokes(): Observable {
        return this.http.get(`${this.base_Url}/random`)
      }
    
    
      extractJokes() {
        this.getJokes ().subscribe(res => {
          console.log(res);
        },
        err => {
          console.log(err);
          this.handleError (err.message);
        });
      }
    
      handleError (err) {
        alert(err);
      }
    }
    

    I created a new handleError method that alerts the user of the error, I also added a second argument which takes the error , log it to browser’s console and invoke the handleError function with the error passed as argument.

    Now let’s simulate an error scenario, take your browser offline and click the button to test.

    Error handling in AngularNotice how I turned my browser offline. You should get an alert like this

Error handling in Angular

This tells us that there is an http failure response. Now the user knows about the error, better, yeah? J, but we can do better.

Now let’s re-jig our code. Starting with getJokes method in our service.

 

import { retry, catchError } from 'rxjs/operators'

We need to import the retry and catchError operators from rxjs/operators. retry will help us retry the http request as many times as specified before throwing error, catchError will throw the error to the user.

Now modify the getJokes, extractJokes and handleError methods as shown below;

 


    getJokes (): Observable {
        return this.http.get(`${this.base_Url}/random`)
        .pipe (
        retry (3),
        catchError(this.handleError)
        )
    }
    
     extractJokes () {
        this.getJokes (). subscribe(res => {
         console.log(res);
     });
     }

      handleError(err) {
        let errorMessage = '';
        if (err.error instanceof ErrorEvent) {
        // if error is client-side error
        errorMessage = `Error: ${err.message}`;
        } else {
        // if error is server-side error
        errorMessage = `Error Code: ${err.status}\nMessage: ${err.message}`;
        }
        alert(errorMessage);
        return throwError(errorMessage);
    }

Remember I stated earlier that errors could either be client or server error, so we need to catch whichever one that happens. So whenever we click the button to make the http request, we have successfully handle whichever kind of error that occurs.

The second way of handling error is with the use of HttpInterceptor which was introduced with Angular 4.3.1. HttpInterceptor is used to intercept all http requests and responses and optionally transform it. HttpInterceptor is an interface that can be implemented by a class, it has an intercept method which takes all the logic to be implemented when the http requests get intercepted. You can read more from the official angular documentation .

  • Create a new class HttpInterceptor.ts

  import { HttpInterceptor, HttpEvent, HttpHandler, HttpRequest } from '@angular/common/http';
  import { Observable } from 'rxjs';
  import { Injectable } from '@angular/core';

 @Injectable ({
    providedIn: 'root'
  })
  export class HttpInterceptorClass  implements HttpInterceptor {
      intercept (req: HttpRequest, next: HttpHandler): Observable<HttpEvent> {
        console.log('Intercepted');
        return next.handle (req);
    }
  }

We need to add the new class to the list of providers in app module.


import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { HttpInterceptorClass } from  './HttpInterceptor';

providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: HttpInterceptorClass,
            multi: true
        }

    ],

Notice how HTTP_INTERCEPTORS was imported form @angular/common/http. If you click the button to make the http request, the request will be intercepted and ‘intercepted’ will be logged to the browser’s console.

Error handling in Angular

Yaay, we have now been able to intercept all our request and successfully log a message to the console on every request. With this we can put in our error handling logic here. Edit the HttpInterceptor file as shown below


    export class HttpInterceptorClass  implements HttpInterceptor {
    intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent> {
      console.log('Intercepted');
      return next.handle(req)
      .pipe(
        retry (3),
        catchError (( err : HttpErrorResponse) => {
          let errorMessage = '';
          if (err.error instanceof ErrorEvent) {
            // client-side error
            errorMessage = `Error: ${err.message}`;
          } else {
            // server-side error
            errorMessage = `Error Code: ${err.status}\nMessage: ${err.message}`;
          }
          alert(errorMessage);
          return throwError(errorMessage);
        })
      )
    }
}

Using HttpInterceptor allows us to have a proper separation of concerns which is exactly what Angular preaches as best practice. If we want to change the way we push error to the user in any part of our application, we can simply do that in the Interceptor class created, this way we can handle errors properly and globally within the application.

Here we come to the end of the tutorial, we have been able to demonstrate different ways of handling errors in our angular application.

You can access the source code here

Chapter 2 of 2Next