Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to handle 'handleError ` and `extractData` private methods

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')
        );
    }
  }

}
like image 920
Sampath Avatar asked Mar 18 '17 10:03

Sampath


1 Answers

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);
  }
}
like image 112
yurzui Avatar answered Nov 15 '22 15:11

yurzui