Being able to make http requests is a very important part of a single page application. In this post I will show a quick demo of how to make requests using the Angular http module.

The http service in Angular is using Observables, which is different from the promise based approach in Angular 1.x. You can still use promises with the new implementation, but this article will focus on the new Observable API.

Below is a simple example where I load a list of friends from a json file:

Simple Get Call

import {Component} from '@angular/core'; import {Http, Response} from '@angular/http' @Component({ selector: 'http', templateUrl: './components/http/http.html' }) export class HttpSample { result: Object; constructor(http: Http) { this.result = {friends:[]}; http.get('./friends.json').map((res: Response) => res.json()).subscribe(res => this.result = res); } }

Via the subscribe function the code reacts to the result of the asynchronous request and deserializes the returned json into an object. The friends array on the returned object is then bound to the view.

Error handling

The above call does not include error handling, but it can easily be added as a second parameter to the subscribe method as seen below. Now, in the case of a failed call, the error will be captured in this.error.

this.http.get('./friends2.json') .map((res: Response) => res.json()) .subscribe(res => this.result = res, error => this.error = error );

Dependent calls

Another common scenario is a call sequence of dependent http calls. In the below example I will make an initial call to load a customer. The returned customer object contains a contract url that I will be using to load a contract for that particular customer.

this.http.get('./customer.json').map((res: Response) => { this.customer = res.json(); return this.customer; }) .flatMap((customer) => this.http.get(customer.contractUrl)).map((res: Response) => res.json()) .subscribe(res => this.contract = res);

Parallel requests

Another common use case is to make independent requests in parallel. In Angular 1.x this is done using $q.all, but in the new http service, this can be done using the forkJoin operator. The idea is very similar though in that you list out the parallel calls and get the result back in an array. Below is an example of how to request a list of friends and a customer in parallel.

import {Observable} from 'rxjs/Observable'; Observable.forkJoin( this.http.get('./friends.json').map((res: Response) => res.json()), this.http.get('./customer.json').map((res: Response) => res.json()) ).subscribe(res => this.combined = {friends:res[0].friends, customer:res[1]});

Cancel Observables

Observables offer built in support for canceling subscriptions. Cancellation can be beneficial if you inadvertently made an http request and want to cancel the processing of the response.

One application of this might be a master detail grid where a user clicks a row to get more details about a particular item. Since each click triggers an independent ajax call, there is always the chance that we get the results back in the incorrect order. Unsubscribing from the requests before making a new one prevents this.

getCapitol(country){ if(this.pendingRequest){ this.pendingRequest.unsubscribe(); } this.pendingRequest = this.http.get('./country-info/' + country) .map((res: Response) => res.json()) .subscribe(res => this.capitol = res.capitol); }

As you can see from the code, calling unsubscribe() on an active Observable effectively cancels the processing of the http response. This enables to make sure we only honor the latest request and avoid out of order processing of the requests.

Calling unsubscribe directly on the observable is not the only way to cancel a request or ignore “stale” requests, already in flight. It turns out that RxJs supports this scenario more elegantly using the switchMap operator. The purpose of the switchMap is to ensure that our application will throw out any previous requests and guarantee that only the most recent request will be processed. If you think about it, this is perfect for the country – capitol grid sample in my demo. So how do we use switchMap in our code? In my sample I've used an RxJs object called Subject, which is a handy object that can double as an observer and an observable.

The code below shows how to use the Subject to trigger a country change and a subsequent http call to get the capitol of that specific country.

First we declare the Subject

country = new Subject();

On button click I am passing in a specific country to the 'next' method on Subject.

country.next('usa')

Then as we receive events from the observable we can react to the changes and make the appropriate http call.

this.country .switchMap((country) => this.http.get('./country-info/' + country + '.json')) .map((res: Response) => res.json()) .subscribe(res => this.capitol = res.capitol);

With just a few lines of code we have added a safeguard into our application that will ensure that we don't have to worry about out of order http requests. You can actually observe that requests are being cancelled in the browser's network tab by clicking the rows very fast.

This is actually pretty cool and I want to give a shoutout to Rob Wormald from the Angular team for pointing me in the direction of switchMap.

Simple Post Call

Post calls are relatively straight forward, just specify a payload and a header.

var headers = new Headers(); headers.append('Content-Type', 'application/json'); this.http.post('your-post-url-goes-here', {firstName:'Joe',lastName:'Smith'}, {headers:headers}) .map((res: Response) => res.json()) .subscribe((res:Person) => this.postResponse = res);

Promises

Angular has moved in the direction of Observables but it's still possible to work with promises if that is your preference. Here is a quick sample where I show how to make an http request using a promise.

this.http.get('./friends.json').toPromise() .then((res: Response) => { this.friendsAsPromise.friends = res.json().friends; });

The way you tell http that you want a promise returned is by calling the toPromise method.

As always – the full example with a live demo can be found here. The code is available on Github. I also have several other Angular samples here.