Angular HTTP Client

The HTTPClient is used to make http call to the server. The HttpClientModule contains all the necessary class to make http call.

In this tutorial, we shall discuss on, how to use HTTP Client along with error handling in angular.

First, we shall see how to create a service that can be used to make a request call to an API, and process the success as well as error, if thrown during the API call.

Create a new angular application using

ng new http-tutorial

This creates a new angular application.

The HttpClient class will help in making api call to the server. In order to use HttpClient, we need to import HttpClientModule from @angular/common/http and register it imports an array of app.module.ts file.

Once you update your app.module.ts it looks as below.

import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing-module';
import { AppComponent } from './app.component';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    AppRoutingModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now, it's time to create a new service that handles the HTTP request calls. To create a service we use

ng g s services/http

Here, g stands for generate, s stands for service and services/http tells angular cli to create a HttpService service in the services folder.

Open the http.service.ts file and modify the code as below

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class HttpService {

  constructor(private http: HttpClient) { }

// Method to make get api call.
  getCall(url: string): Observable<any> {
    return this.http.get(url).pipe(
      retry(1),
      catchError(this.errorHandler)
    );
  }
  
// Method to make post api call.    
  postCall(url: string, data: string): Observable<any> {
    return this.http.post(url, data)).pipe(
      retry(1),
      catchError(this.errorHandler)
    );
  }

// Handle http error if any.
  errorHandler(error: HttpErrorResponse): Observable<never> {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      // client-side error
      errorMessage = `Error: ${error.error.message}`;
    } else {
      // server-side error
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    return throwError(errorMessage);
  }
}

Let's see the coding one by one. Here in order to use HttpClient, we need to import it from @angular/common/http. Then we will inject the HttpClient to the constructor of the service with the parameter name http.

Next, create two functions named getCall() and postCall().

The getCall() function which takes a URL as a parameter. It is used to make get requests using the http variable and call get method with URL as parameter.

Similarly, postCall() function which takes a URL and the data object as parameter calls post method using http variable.

In order to handle the error occurred when making the api call we use catchError operator of rxjs.

this.http.get(url).pipe(
      retry(1),
      catchError(this.errorHandler)
    );

In the above code snippet, using this.http.get(url) we will make a call to a particular API, and then we pipe the request. The need for the pipe is to perform any transformation operation.

We use retry operator of rxjs to retry calling API if it fails for the first time. This takes an integer as a parameter to specify how many times it should retry if it fails in making the API call.

The catchError() operator of rxjs is used to handle the error. This takes a function with HttpErrorResponse as parameter. We have written a function named error handler to perform the error handling operation.

Let's get closer look to the function

errorHandler(error: HttpErrorResponse): Observable<never> {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      // client-side error
      errorMessage = `Error: ${error.error.message}`;
    } else {
      // server-side error
      errorMessage = `Error: ${error.message}`;
    }
    return throwError(errorMessage);
  }
}

The parameter named error of type HttpErroResponse will hold an error of, either type ErrorEvent which denotes that its client-side error, or HttpErrorResponse which denoted error thrown by or occurred at the server.

Check whether the error is an instance of ErrorEvent if so then its client-side error, else its server-side error.

Next, modify the error message and return it using throwError operator which returns an Observable.

Next, let's use this HttpService in a component. Let's check it in AppComponent component.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { HttpService } from '../services/http.service';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit, OnDestroy {

  subscriptionObject = {};
  constructor(private httpService: HttpService) { }

  ngOnInit() {
    const usersApiUrl = 'https://reqres.in/api/users?page=2';
    // tslint:disable-next-line: no-string-literal
    this.subscriptionObject['userList'] = this.httpService.getCall(usersApiUrl).subscribe((value) => {
      console.log(value);
    }, (error) => {
      console.log(error);
    });
  }

// Unsubscribe all the observables.
  ngOnDestroy(): void {
    const subscribers = Object.keys(this.subscriptionObject);
    subscribers.forEach((value) => {
      this.subscriptionObject[value].unsubscribe();
    });
  }
}

In the above code, the HttpService is injected to the constructor and getCall() function is called, which returns an Observable.
Subscribe to the observable, it returns the result or the error.

If there is no error, then the first callback function of the subscribe will be called with the returned result value. If there is any error, then the second callback function of the subscribe will be called.

Generally, it's necessary to unsubscribe anything that has been subscribed, so I had created a subscriptionObject and assign subscriptions to it.

Finally, I had unsubscribed it in ngOnDestroy() life cycle event of angular by looping through the subscriptionObject.

If we need to add any headers to the request call, we can achieve it by using HttpHeaders. Let's just see how to add a header to a post request.

postCall(url: string, data: string): Observable<any> {
    const headers = new HttpHeaders({ 'Content-Type': 'application/json' });
    const options = {
      headers:headers
    };
    return this.http.post(url, data, options);
  }

Here we have create a HttpHeaders object set the Content-Type property to application/json and provide it as an option to the post method.

Finally, a service to handle API calls with both get and post method with error handling is ready for use.


Most Read