Http service in Angular 2

Use the http service in Angular 1 meant to deal with promises and defer, because it was based on APIs exposed by the $q service.

Angular 2 makes a step ahead and the new implementation of the http service involves the observable pattern, with the using of RxJS javascript library.

Why this big change? Because an observable is a powerful way to observe the behavior of a variable and its changes, for example when we assign a value or change it.

What we can do to use the http service efficiently is implement a typescript class that exposes the CRUD operation on a generic entity, based on a Web API.

Base class

This class exposes five basic methods to do simple CRUD operations; the first step is import the libraries:


import { Http, Response, Headers, RequestOptions } from "@angular/http";
import { Observable } from "rxjs/Observable";

We import a bunch of objects of the http angular library and the observable library.

Now we can implement the class:


export class WebApi<T> {
protected url: string;
protected options: RequestOptions;

constructor(url: string, public http: Http) {
this.url = url;
let headers = new Headers({ "Content-Type": "application/json" });
this.options = new RequestOptions({ headers: headers });
}

public GetAll(): Observable<T[]> {
return this.http.get(this.url, this.options).map(this.extractData).catch(this.handleError);
};

public Get(id: string): Observable<T> {
return this.http.get(this.url + "/" + id, this.options).map(this.extractData).catch(this.handleError);
}

public Put(id: string, entity: T): Observable<boolean> {
return this.http.put(this.url + "/" + id, JSON.stringify(entity), this.options).map(this.extractResponseStatus).catch(this.handleError);
}

public Post(entity: T): Observable<T> {
return this.http.post(this.url, JSON.stringify(entity), this.options).map(this.extractData).catch(this.handleError);
}

public Delete(id: string): Observable<boolean> {
return this.http.delete(this.url + "/" + id, this.options).map(this.extractResponseStatus).catch(this.handleError);
}

protected extractData(res: Response) {
let body = res.json();
return body || {};
}

protected handleError(error: any) {
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg);
return Observable.throw(errMsg);
}

private extractResponseStatus(res: Response) {
return res.ok;
}
}

This is a typed class, with it we are able to define an instance of the class for a specific entity.

All the methods return an Observable property, dealing with the http service; every observable response uses a method to return the json part of the response and another method to handle and log response errors.

This is a class that will be used for our services.

The service

A specific service extends the base class and it can add some specific methods.

The implementation is look like this:


import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import { Customer } from "./customer.model";
import { WebApi } from "../shared/webapi";

@Injectable()
export class CustomerService extends WebApi<Customer> {
constructor(public http: Http) {
super("/api/customers", http);
}
}

The service extends the WebApi typed class and injects the base url of the Web API and the http service instance.

Using

In a controller we can use the service to retrieve the list of the customers:


.....

import { CustomerService } from "./customer.service";
.....
export class CustomerComponent implements OnInit {
.....
constructor(private customerService: CustomerService, .....) {}

ngOnInit() {
.....
this.Load();
}

public Load() {
.....
this.customerService.GetAll().subscribe(
(data) => {
.....
this.customers = data;
.....
},
(error) => this.alertService.Error(error));
}
}

As you seen above, the GetAll method returns an observable property, so in order to retrieve the reponse, we need to subscribe to it.

The subscribe method can accepts two functions as parameters; the first one will be called if we’ll receive a successfully response; the second one will be executed if an error occurred.

The source code of this topic is available here.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

Up ↑

%d bloggers like this: