angular2 – 多次处理相同的响应错误

angular2 – handle same response error multiple times

我正在构建一个 angular2 应用程序。我有一个名为 HttpClient 的全局服务,它在 angulars 内置 http 服务被触发之前处理所有请求。此服务还通过检查状态代码来处理我所有的响应错误:

import { Injectable } from '@angular/core';
import { Headers, Http, Response, } from '@angular/http';

import { MessageProvider } from '../../providers/message/message.provider'

@Injectable()
export class HttpClient {

    private webApi = 'http://localhost:8080/api/v1/';

    constructor(
        private http: Http,
        private messageProvider: MessageProvider) { }

    get(url: string): Promise<Response> {
        return this.http.get(this.webApi + url, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    post(url: string, data: Object): Promise<Response> {
        return this.http.post(this.webApi + url, data, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    put(url: string, data: Object): Promise<Response> {
        return this.http.put(this.webApi + url, data, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    delete(url: string): Promise<Response> {
        return this.http.delete(this.webApi + url, {headers: this.createAuthorizationHeader()})
                        .toPromise()
                        .catch(this.handleError.bind(this));
    }

    private handleError (error: any) {

        var status: number = error.status;

        if(status == 401) {
            this.messageProvider.setMessage(error);
            this.messageProvider.message.text = "You have to be logged in to reach this page.";
        }


        let errMsg = (error.message)
            ? error.message
            : status
                ? `${status} - ${error.statusText}`
                : 'Server error';

        console.error(errMsg); // log to console instead

        return error;
    }

    private createAuthorizationHeader() {

        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        headers.append('Accept', 'application/json');

        if (localStorage.getItem('token'))
            headers.append('Authorization', 'Bearer ' + localStorage.getItem('token'));

        return headers;
    }
}

现在,假设调用组件是关于登录的:

import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { Router } from '@angular/router';

import { Login } from '../../core/classes/login/login'

import { AuthenticationProvider } from '../../providers/authentication/authentication.provider'
import { MessageProvider } from '../../providers/message/message.provider'

@Component({
  selector: 'my-login',
  templateUrl: 'app/components/login/login.component.html'
})
export class LoginComponent implements OnInit, OnDestroy {

  @Input() login: Login;
  error: any;

  constructor(
    private authProvider: AuthenticationProvider,
    private route: Router,
    private messageProvider: MessageProvider) { }

  ngOnInit() {
    this.login = new Login();
  }

  ngOnDestroy() {
    this.messageProvider.setDefault();
  }

  onSubmit() {
    this.authProvider.login(this.login)
        .then(auth => {
            if (this.authProvider.isAdmin())
                this.route.navigateByUrl('admin/users');

            else if (this.authProvider.isLoggedIn())
                this.route.navigateByUrl('/');
            })
            .catch(error => {console.log(error);});
  }
}

在这种情况下,我不想要来自 HttpClient ("You have to be logged in to reach this page.") 的错误,而是更自定义的消息,如 "No user found"。我知道我可以做类似下面的事情,但不再有错误:

onSubmit() {
    this.authProvider
        .login(this.login)
        .then(auth => {
            if (this.authProvider.isAdmin())
                this.route.navigateByUrl('admin/users');

            else if (this.authProvider.isLoggedIn())
                this.route.navigateByUrl('/');
            })
            .catch(error => {
                var status: number = error.status;

                if(status == 401) {
                    this.messageProvider.setMessage(error);
                    this.messageProvider.message.text = "No user found.";
                }
            });
}

那么有没有办法在 HttpClient 中的 catch() 函数中引起另一个错误?所以我可以在我的 LoginComponent 中再次处理错误。

我认为你可以在 catch 方法中抛出本质上 "map" 你的错误。如果你还想更新你的 messageProvider 那么你可以做...

.catch(error => {
    var status: number = error.status;
    var newError = {};
    if(status == 401) {
        this.messageProvider.setMessage(error);
        this.messageProvider.message.text = "No user found.";
        newError.errorMessage = "No user found.";
    }
    throw newError;
});

用这个例子确认:

  var obs = Observable.of(12);
  obs.map((value) => {
    throw "blah";
  }).catch((error) => {
    if(error === "blah") {
      throw "baz";
    } else {
     return Observable.of("Hello");
    }
  }).subscribe((value) => {
    console.log("GOOD: " + value);
  }, (error) => {
    console.log("ERR: " + error);
  });
  //Logs ERR: baz