Sunday, June 26, 2016

Implementing HTTP Client in Angular 2 using Observables (RxJS) and Promises


Angular 2 provides a choice between Observables and Promises for developing a HTTP client that invokes server side API. This blog discusses the two options.


RxJS Introduction - Reactive Extensions (Rx) is a Microsoft backed open source project. It is an event driven, asynchronous design approach. It helps develop effectively for a stream of data returned through asynchronous and time consuming operations. The async operation could be network operations, UI interactions, file IO etc. There are Rx libraries available for galore of programming languages like C#, Python, JavaScript, Java so on. Follow this link for a complete list. As you might have guessed, RxJS is JavaScript library for Reactive Extensions.

Angular 2, RxJS and Promises- At first, let us look at Angular 2's usage of RxJS for making HTTP calls. Later in the blog, we will review promises.

HTTP calls are asynchronous in JavaScript. Earlier implementations of Angular (1.x) used promises. It has success and error callbacks that are invoked when the call is done.

Angular 2 provides a choice between RxJS and Promises. Observables support stream of data, where as promises are done once the current invocation is complete. And also, observables could be cancelled (or unsubscribed).

While RxJS 4 focussed on ES 5 implementation, RxJS 5 is a rewrite for ES 2015 (ES 6). For more details on RxJS 5, follow this link to GitHub Repo. It is in beta at the time of writing this blog.

Note: My previous blog discusses RxJS 4 in an Angular 1.x application. Follow the link to check-out the blog.

A Sample implementation - Just so that focus is on demonstrating HTTP client, will take a very simplistic code sample. It shows list of players (sports stars) on a page. The list is obtained from a node service (server side) over a HTTP GET call, on click of a button. Consider following image.


We will be implementing this using Angular 2 and TypeScript.

The code to retrieve players is encapsulated in playerService.ts Consider following code. Read through the comments for details on each line of code.

// Injectable decorator for allowing a class to be exported as service/provider.
import {Injectable} from '@angular/core';

// Http and Response for making HTTP calls
import {Http, Response} from '@angular/http';


// RxJS Observable

import {Observable} from 'rxjs/Observable'

// Get everything rxjs
import 'rxjs/Rx';

// Injectable decorator for allowing a class to be exported as service/provider.
@Injectable()
export class PlayerService {
   

    // inject Http instance for making HTTP calls.
    constructor(private http: Http){}


    getData(): Observable<Response> {
        return this.http.get('api/search');
    }
}


Consider the getData() function, it returns an observable of HTTP response. 

What is an obserable? It is an array or stream of data made available asynchronously. As the term indicates it is an object that could be observed for data to be made available. The observable emits data only when there is an observer. In other words, the observable could be subscribed to by an observer.

Consider following code. It is a function in an Angular 2 component. This component is bound to a UI template. The component subscribes to the observer on click of the button with caption "Get player list".

  getData(){
    this.serviceInstance
      .map(result => result.json())
      .subscribe( result => this.players = result);
  }


Following the link for the complete component class.

map is an RxJS operator for transforming the response to player list. The players array on the component is bound to the associated view/template. Refer to the following template code. ngFor iterates through players array. Bindings on JSON properties can be seen with-in the curly braces - {{}}.

    <div *ngFor="let item of players">
        <div>
            <strong>{{item.name}}</strong>
            <div><span>{{item.age}}</span> . <span>{{item.gender}}</span></div>
            <div>{{item.email}}</div>
            <div><hr></div>
        </div>
    </div>


Promises - Above functionality could be achieved using familiar promises as well. Observables are advisable for their sophistication. But if you prefer to stick to promises, API is available.

Promise too is asynchronous. After making a HTTP call. success or error callback are invoked with the response. Consider following code snippet in the service class (playerService.ts). It returns promise of HTTP response.

    getDataAsAPromise(): Promise<Response> {
        return this.http.get('api/search').toPromise(); // toPromise() is responsible for obtaining a promise from the get call.
    }


Consider following code. In the calling function, as the promise is resolved, one of the "then function callbacks" are invoked. First parameter is a success callback. Second parameter is an error callback. The success callback sets result on component's players array, which has bindings in the template. (refer to the template/HTML code in above section)

  getDataAsAPromise(){
    this.service.getDataAsAPromise().then( result => this.players = result.json(), error => console.log(error));
  }


Follow this link for complete code sample. "Read me" file has details to run the sample.


References

https://github.com/ReactiveX/rxjs
https://angular.io/docs/ts/latest/guide/server-communication.html#!#http-client
http://reactivex.io/languages.html
https://msdn.microsoft.com/en-in/data/gg577609.aspx

No comments:

Post a Comment