According to the Angular doc the best way of handling observable as shown below.My question is, can you suggest me to a good coding practice to avoid usage of handleError
and extractData
private methods again and again on each and every service? How can I declare it once and use everywhere?
getHeroes(): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
private handleError (error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
Update:
handle-observable-service.ts
import { Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
export abstract class HandleObservableService {
//to handle error
protected handleError(error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
//to extract data
protected extractData(res: Response) {
let body = res.json();
return body.data || {};
}
}
authentication-data.ts
import { Injectable } from '@angular/core';
import { Http, RequestOptions, Headers, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import { HandleObservableService } from "../utility-services/handle-observable-service";
@Injectable()
export class AuthenticationData extends HandleObservableService {
authenticationEndPoint: string = "https://www.myk.com/admin/index.php?route=api/login&username=";
constructor(public http: Http) {
super();
}
//to login
loginUser(username: string, password: string): Observable<any> {
let headers = new Headers();
headers.append('content-type', 'application/json');
let body = '';
let options = new RequestOptions({ headers: headers });
let url = this.authenticationEndPoint + encodeURI(username) + '&password=' + encodeURI(password);
return this.http.post(url, body, options)
.map(this.extractData)
.catch(this.handleError);
}
}
login.ts
import { Component } from '@angular/core';
import { NavController, NavParams, AlertController } from 'ionic-angular';
import { AuthenticationData } from "../../providers/authentication-data";
import { FormBuilder, Validators } from "@angular/forms";
import { Storage } from '@ionic/storage';
@Component({
selector: 'page-login',
templateUrl: 'login.html'
})
export class LoginPage {
response: any;
loginForm: any;
constructor(public navCtrl: NavController, public navParams: NavParams, public authenticationData: AuthenticationData,
public formBuilder: FormBuilder, public storage: Storage, public alertCtrl: AlertController) {
this.loginForm = formBuilder.group({
username: ['', Validators.required],
password: ['', Validators.compose([Validators.minLength(4), Validators.required])]
});
}
ionViewDidLoad() {
}
//to login
loginUser(): void {
if (this.loginForm.valid) {
this.authenticationData.loginUser(this.loginForm.value.username, this.loginForm.value.password)
.subscribe(data => {
if (data.token != null && data.token != '') {
this.storage.ready().then(() => {
this.storage.set('token', data.token);
});
this.navCtrl.pop();
} else {
let alert = this.alertCtrl.create({
title: 'Error',
subTitle: 'User Name or Password is wrong',
buttons: [{
text: 'OK',
handler: data => {
}
},]
});
alert.present();
}
},
err => {
console.log(err);
},
() => console.log('Complete')
);
}
}
}
You can create base class like:
base.service.ts
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
export abstract class BaseService {
protected handleError (error: Response | any) {
// In a real world app, you might use a remote logging infrastructure
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
}
protected extractData(res: Response) {
let body = res.json();
return body.data || { };
}
}
and then HeroService
will extend it:
hero.service.ts
import { BaseService } from './base.service';
class HeroService extends BaseService {
constructor(private http: Http) {
super();
}
getHeroes(): Observable<Hero[]> {
return this.http.get(this.heroesUrl)
.map(this.extractData)
.catch(this.handleError);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With