Angular 4.3 brings us a new easier way to handle http requests with the HttpClient library. It’s available under a new name to avoid causing breaking changes with the current Http library. HttpClient also gives us advanced functionality like the ability to listen for progress events and interceptors to monitor or modify requests or responses.
Make sure you’re using Angular 4.3 or above to try out HttpClient
Installation
First, you’ll need to import HttpClientModule from @angular/common/http in your app module:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
And then you can use the HttpClient just as you would normally:
some.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable()
export class DataService {
constructor(private http: HttpClient) {}
Basic Usage
Making basic GET, POST, PUT, PATCH or DELETE requests is very similar to what you’re used to with the old Http API. One major difference is that a JSON response is expected by default, so there’s no need to explicitly parse the JSON response anymore.
Here’s a sample GET request:
// ...
constructor(private http: HttpClient) {}
getData() {
this.http.get(this.url).subscribe(res => {
this.posts = res;
});
}
If you expect something else than JSON as the response, you can specify the expected response type using an object with the responseType key:
getData() {
this.http.get(this.url, { responseType: 'text' }).subscribe(res => {
this.data = res;
});
}
You can also define an interface for the shape of the response and type-check against that interface:
interface Post {
title: string;
body: string;
};
// ...
constructor(private http: HttpClient) {}
getData() {
this.http.get<Post>(this.url).subscribe(res => {
this.postTitle = res.title;
});
}
By default the HttpClient returns the body of the response. You can pass-in an object with an observe key set to a value of ‘response’ to get the full response. This can be useful to inspect for certain headers:
getData() {
this.http.get<Post>(this.url, { observe: 'response' }).subscribe(res => {
this.powered = res.headers.get('X-Powered-By');
this.postTitle = res.body.title;
});
}
Post, put and patch requests
Making a POST, PUT or PATCH request is just as easy:
postData() {
this.http.post(this.url, this.payload).subscribe();
}
Notice how we still have to subscribe in order for the request to be made. Without the subscribe call, the request is cold. You’ll obviously probably want to handle any response back or error:
postData() {
this.http.post(this.url, this.payload).subscribe(
res => {
console.log(res);
},
(err: HttpErrorResponse) => {
console.log(err.error);
console.log(err.name);
console.log(err.message);
console.log(err.status);
}
);
}
A request error is of type HttpErrorResponse and contains, among others, an error name, error message and server status.
Options for passing-in headers or query parameters can also be added to a POST, PUT or PATCH request using the headers or params keys in the object passed-in as the 3rd argument:
updatePost() {
this.http
.put(this.url, this.payload, {
params: new HttpParams().set('id', '56784'),
headers: new HttpHeaders().set('Authorization', 'some-token')
})
.subscribe(...);
}
Notice here the use of the HttpParams and HttpHeaders classes. You’ll need to import these from @angular/common/http as well.
Progress Events
A great new feature with HttpClient is the ability to listen for progress events. This can be done on any type of request and different information will be available during the lifecycle of the request event. Here’s a full example with a GET request:
import { Injectable } from '@angular/core';
import {
HttpClient,
HttpRequest,
HttpEvent,
HttpEventType
} from '@angular/common/http';
@Injectable()
export class DataService {
url = '/some/api';
constructor(private http: HttpClient) {}
getData() {
const req = new HttpRequest('GET', this.url, {
reportProgress: true
});
this.http.request(req).subscribe((event: HttpEvent<any>) => {
switch (event.type) {
case HttpEventType.Sent:
console.log('Request sent!');
break;
case HttpEventType.ResponseHeader:
console.log('Response header received!');
break;
case HttpEventType.DownloadProgress:
const kbLoaded = Math.round(event.loaded / 1024);
console.log(`Download in progress! ${ kbLoaded }Kb loaded`);
break;
case HttpEventType.Response:
console.log('😺 Done!', event.body);
}
});
}
}
We first need to build a request object by creating an instance of the HttpRequest class and using the reportProgress option.
We then subscribe to our request object to initiate the request and listen to the different event types over the life of the request. We can react appropriately depending on the event type. The available event types are Sent, UploadProgress, ResponseHeader, DownloadProgress, Response and User.
In the above example, we get the amount of data downloaded so far from the GET response, and in the case of something like a POST or PUT request we could also get the percentage of the payload uploaded by using something like 100 * event.loaded / event.total
. This makes it very easy to show a progress bar to the user.
🤓 This post covered the basics of HttpClient, and next will tackle the use of interceptors, the killer feature of HttpClient. You can also head over to the official docs to go more in-depth.