【问题标题】:Best practice to handle 'handleError ` and `extractData` private methods处理“handleError”和“extractData”私有方法的最佳实践
【发布时间】:2017-08-09 22:19:06
【问题描述】:

根据Angular doc 处理 observable 的最佳方法如下所示。我的问题是,你能建议我一个好的编码实践来避免在每个上一次又一次地使用 handleErrorextractData 私有方法和每一项服务?如何声明一次,到处使用?

    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 || { };
  }

更新:

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 || {};
  }
}

身份验证数据.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')
        );
    }
  }

}

【问题讨论】:

  • 你可以使用基类来定义这些方法
  • 如果你不介意可以请你做个小代码sn-p解释一下吗? @yurzui
  • 声明一次,到处使用?

标签: angular typescript ionic-framework ionic2 observable


【解决方案1】:

你可以像这样创建基类:

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 || { };
  }
}

然后HeroService 将扩展它:

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

【讨论】:

  • 我已经如上所示实现了它。但是当我从不同的ts 文件subscribeobservable 时,它不返回使用this.extractData 方法提取的值。你知道为什么?但它很好地提取了BaseService 中的值。但它似乎对订阅者方法不可见。这是为什么呢?
  • 您能否也实现subscriber 部分?
  • return body.data || { } 的值似乎只在BaseService 类中可见。它不会返回到subscriber 方法。如何解决这个问题?
  • 你试过heroServie.getHeroes().subscribe((data) =&gt;吗?
  • 是的,我试过这种方式。但是extractData方法的返回值是undefine。换句话说,heroServie.getHeroes().subscribe((data) =&gt; 这里的dataundefine。为什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-02
  • 1970-01-01
  • 2013-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多