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.