Error handling in Angular

Error handling in Angular

In this tutorial, we are going to demonstrate how to handle errors properly in our Angular applications... 👏👏👏👏👏

Error handling in software development is as important having a working application. In order to have a complete and robust application, errors and exceptions have to be properly handled. Handling errors is a way of telling your users “hey dude! Calm down, here is the problem and here is the way out”, assurance, yeah? :).

In this tutorial, I will walk you through how to efficiently handle errors in your Angular Application. I will be using latest version of  Angular 7.0.4 for this tutorial and I will advise you use the same.

Prerequisites

For the purpose of this tutorial the following has to be available on your system;


  1. Install Node
  • Go to nodejs
  • Download and install the available LTS version.
  • To check your version, run node -v in a terminal/console window.
  1. Install Angular CLI
 npm i -g @angular/cli 
  1. BashCopy
  2. Visual Studio Code. I use VSCode but you can choose to use any other IDE (Angular IDE, Atom, Vim etc.)

With all these prerequisites in place, we can start by creating a new folder for our application.

  • Open the folder in VSCode by right clicking in the folder and open with VSCode.
  • Open VsCode terminal and create a new angular project
      ng new my-ErrorHandling-app 

  • BashCopy
  • The ng newcommand prompts you for information about features to include in the initial app project. Accept the defaults by pressing the Enter or Return key.
  • Cd into the project folder cd myErrorHandlingApp
  • Serve the application locally.
      ng serve -o 
  • BashCopy

This will open the application in your local browser on localhost:4200, you should see this

Error in Angular application can either be a Client-Side error or Server-Side error;

  • Client-side error: These are errors related to Front-end code and the Network, they throw 4xx status codes.
  • Server-side error: These are errors related to Back-end codes, database and file system. They usually throw 5xx status codes.

For the purpose of this tutorial, we are going to demo error handling by consuming chucknorris API to display random jokes using Angular’s in-built HttpClientModule.


We start by importing HttpClientModule to our root module (app.module.ts).

       import { BrowserModule } from '@angular/platform-browser';
       import { NgModule } from '@angular/core';
       import { HttpClientModule } from '@angular/common/http';
       import { AppRoutingModule } from './app-routing.module';
       import { AppComponent } from './app.component';

      @NgModule({         declarations: [           AppComponent        ],        imports: [           BrowserModule,           HttpClientModule,           AppRoutingModule       ],        providers: [],        bootstrap: [AppComponent]       })       export class AppModule { }

In app.component.html, we create a button which will initiate an http request on click.

In app.component.ts, we include our constructor function and extend the component’s class to implement OnInit lifecycle hook.

       
  import {Component, OnInit} from '@angular/core';

  @Component ({     selector: 'app-root',     templateUrl: './app.component.html',     styleUrls: ['./app.component.scss']   })   export class AppComponent implements OnInit {     title = 'my-app'; constructor () {}

  makeApiCall () {     }

  ngOnInit () {}    }

Now we need to create a service where we will make our http request. Service is a very important component of Angular. When we need to have some codes to be used everywhere in the application or we need to pass data across the application, services will come in handy.

ng g service appService

JsCopy

This will create a new Injectable service that can be injected into all our components. We should have this on our folder tree now.

After creating the service, we will inject the service into app component controller (app. component.ts file). Notice how the appService is imported into the component.

       
  import {Component, OnInit} from '@angular/core';
  import {AppServiceService } from './app-service.service';
  @Component ({
     selector: 'app-root',
     templateUrl: './app.component.html',
     styleUrls: ['./app.component.scss']
  })
  export class AppComponent implements OnInit {
    title = 'errorHandling-app';
    constructor (appService: AppServiceService) {
          }
    ngOnInit() {}
}

In the appService, we will make our http request to chuck Norris open API to get random jokes.

       
    import { Injectable } from '@angular/core';
  import { HttpClient } from '@angular/common/http';

  @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);       })     }   }

So, what have I done?

  • I set the base URL for our API to ‘https://api.chucknorris.io/jokes’
  • I injected HttpClient service as a private variable in the constructor function. N.B. You need to import HttpClientModule into app.module.ts from ‘@angular/common/http.
  • I created a getJokes that invokes the http get method to fetch random jokes. This is returned as Observables.
  • In the extractJokes method, I subscribe to the jokes Observable and logging it on the console.

So, what have I done?

Well, I think the next thing we need to do is to call the extractJokes method from controller on click of the button. In the makeApi method, insert this;

      makeApiCall() {
         this.appService.extractJokes();
       }

JsCopy

Now, save your code and click on the button, you should see a joke object on your browser’s console.

Works fine right? :)

We are done with the application and ready to ship. Oh wait!!! What happens if there is any error from our http request, how do we let the user know of the error, how do we handle that.

Now there are many ways of doing this, in the next chapter of this tutorial, let’s explore some of them.

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);   } }

  1. 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.
  2. Now let’s simulate an error scenario, take your browser offline and click the button to test.
  3. Notice how I turned my browser offline. You should get an alert like this

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'

JsCopy

We need to import the retry and catchError operators from rxjs/operators. retrywill 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.

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

*Originally published by  Sulaiman at dunebook.com

===============================================================

Follow me on Facebook | Twitter

Learn More

☞ Angular 7 (formerly Angular 2) - The Complete Guide

☞ Learn and Understand AngularJS

☞ The Complete Angular Course: Beginner to Advanced

☞ Angular Crash Course for Busy Developers

☞ Angular Essentials (Angular 2+ with TypeScript)

☞ Angular (Full App) with Angular Material, Angularfire & NgRx

☞ Angular & NodeJS - The MEAN Stack Guide


Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

Brave, Chrome, Firefox, Opera or Edge: Which is Better and Faster?

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

How to Use Cookies in Angular for Storing user’s Credentials

In this post, I will be explaining about using Cookies in Angular for Storing user’s Credentials

Angular Tutorial - Learn Angular from Scratch

Angular Tutorial - Learn Angular from Scratch: This course is for beginners who are curious on how to get started with Angular. In this course you will learn how to download, install and play around with Angular. We teach you the main components of Angular, so that you can get up and running with it asap. You will learn now to start building applications with Angular.

An Angular Roadmap — The Past, Present, and Future of Angular

✅Interested in being an Angular developer in 2019? ... blog post it's most likely that you've written some code in javaScript in the past.