【问题标题】:handling error with http global service angular 4.3, handleError , 401, 0, etc, interceptor , jwt, headers使用 http 全局服务 Angular 4.3、handleError、401、0 等、拦截器、jwt、标头处理错误
【发布时间】:2018-01-12 17:46:23
【问题描述】:

我有一个 http 全局服务,它被所有服务调用;所以我可以以身作则,做到最好;错误、警报、变量等。

customers.service.ts

export class CustomersService {
  childUrl = environment.apiUrl + 'customers';

  constructor(
    private http: HttpClient,
    private globalService: GlobalService
   ) {


  }

  public get(childUrl)  {
    return this.globalService.get(this.childUrl)
      .catch((res: Response) => this.handleError(res));
  }
  ...
  private handleError(err) {
    return Observable.throw(err);
  }
}

global.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpHeaders  } from '@angular/common/http';
import { environment } from '../../environments/environment';

@Injectable()
export class GlobalService {

  url: string,

  constructor(private http: HttpClient) {

    this.headers = new HttpHeaders()
      .set('Content-Type', 'application/json; charset=utf-8')
      .set('Accept', 'application/json');


  }

  public prepare ( vars ) {
    this.url = environment.apiUrl + vars.childUrl;
  }
  public get( childUrl)  {

    this.prepare ({childUrl} );

    return this.http.get(this.url, { headers: this.headers, observe: 'response'})
      .catch((res: Response) => this.handleError(res);
  }
  private handleError(err) {
    return Observable.throw(err);
  }

}

customers-list.component

export class CustomersListComponent implements OnInit {

  public customers: Array <any>;

  constructor (private customersService: CustomersService ) { }

  ngOnInit() {
    this.get();
  }

  private get(): void {
    this.customerService
      .get()
      .subscribe((data) => {this.customers = data.data; console.log(data) },
        error => console.log(error),
        () => console.log('Get all Items complete'));
  }
}

在 Angular 4.3 之前,我有 observables ,我可以捕获错误,并在组件中的全局服务、子服务中抛出一个 observable。现在它不工作了,我不确定如何管理 catch,并使用 observables 处理错误

在新的角度指南中: https://angular.io/guide/http#error-handling

只需以简单的方式管理错误,

http
  .get<ItemsResponse>('/api/items')
  .subscribe(
    data => {...},
    (err: HttpErrorResponse) => {
      if (err.error instanceof Error) {
        // A client-side or network error occurred. Handle it accordingly.
        console.log('An error occurred:', err.error.message);
      } else {
        // The backend returned an unsuccessful response code.
        // The response body may contain clues as to what went wrong,
        console.log(`Backend returned code ${err.status}, body was: ${err.error}`);
      }
    }
  });

现在管理这个的正确方法是什么?

【问题讨论】:

  • 它正在为我的服务器 API 工作已关闭。

标签: angular jwt


【解决方案1】:

为错误场景定义严格类型,如下所示,

export interface Error{
    code:number;
    error:string[];
    errorType:ErrorType;
}

export enum ErrorType{
    FATAL_ERROR,
    SYSTEM_ERROR
}

使用handleError常用方法进行如下修改处理,

private handleError(error) {
    if(typeof error === Response){
        return Observable.throw(err);
    } else if(typeof error === Error){
        if(error && error.errorMessages && errorMessages.length){
            error.errorMessages.forEach(msg=> console.log(error.error));
        }
    }
}

【讨论】:

    【解决方案2】:

    确实仍然有可观察对象,并且您基本上可以保持现有组件代码不变。您只需更改服务代码即可使用新的HttpClient

    这是我的新服务:

    import { Injectable } from '@angular/core';
    import { HttpClient, HttpErrorResponse } from '@angular/common/http';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/observable/throw';
    import 'rxjs/add/operator/catch';
    import 'rxjs/add/operator/do';
    import 'rxjs/add/operator/map';
    
    import { IProduct } from './product';
    
    @Injectable()
    export class ProductService {
        private _productUrl = './api/products/products.json';
    
        constructor(private _http: HttpClient) { }
    
        getProducts(): Observable<IProduct[]> {
            return this._http.get<IProduct[]>(this._productUrl)
                .do(data => console.log('All: ' + JSON.stringify(data)))
                .catch(this.handleError);
        }
    
        private handleError(err: HttpErrorResponse) {
            // in a real world app, we may send the server to some remote logging infrastructure
            // instead of just logging it to the console
            let errorMessage = '';
            if (err.error instanceof Error) {
                // A client-side or network error occurred. Handle it accordingly.
                errorMessage = `An error occurred: ${err.error.message}`;
            } else {
                // The backend returned an unsuccessful response code.
                // The response body may contain clues as to what went wrong,
                errorMessage = `Server returned code: ${err.status}, error message is: ${err.message}`;
            }
            console.error(errorMessage);
            return Observable.throw(errorMessage);
        }
    }
    

    这是我的组件中的方法,基本上没有改变:

    ngOnInit(): void {
        this._productService.getProducts()
                .subscribe(products => this.products = products,
                    error => this.errorMessage = <any>error);
    }
    

    【讨论】:

      【解决方案3】:

      我终于找到了解决方案,错误是对象,所以在 Angular 4.3 之前,错误对象是一个响应,现在它是 HttpErrorResponse,反正我们得到对象,所以我们可以请求属性。大多数函数不考虑错误状态 0,当服务器不工作时,或者当您的 Angular 4.3 中的拦截器或您在错误管理中所做的任何事情都没有产生正确的状态时。

      我找到的最终解决方案只是简单地从错误对象中询问对象属性,并且我可以定义消息错误以防我不想显示已知错误的后端错误。

      查找 environment.ts 文件(angular-cli 创建此文件):

      export const environment = {
        production: false,
        apiUrl: 'http://localhost:3000/',
        httpErrors: {
          0:   { 'msg': 'Server is not available'},
          404: { 'msg': 'Page not Found'},
          401: { 'msg': 'Not Authorized'}
        }
      };
      

      那么全局服务的处理错误可以是:

        private handleError(err: any) {
          console.log( 'Error global service');
          console.log(err);
          let errorMessage = '';
      
          if (err.hasOwnProperty('status') ) { // if error has status
            if (environment.httpErrors.hasOwnProperty(err.status)) {
               errorMessage = environment.httpErrors[err.status].msg; // predefined errors
            } else {
              errorMessage = `Error status: ${err.status}`;
              if (err.hasOwnProperty('message')) {
                errorMessage +=  err.message;
              }
            }
          }
          if (errorMessage === '') {
            if (err.hasOwnProperty('error') && err.error.hasOwnProperty('message') ) { // if error has status
              errorMessage = `Error: ${err.error.message}`;
            }
          }
          if (errorMessage === '')  errorMessage = environment.httpErrors[0].msg; +// no errors, then is connection error
         this.snackBar.open(errorMessage, 'Close', {
            duration: 5000
          });
          console.error(errorMessage);
          return Observable.throw(errorMessage);
        }
      

      在你的拦截器中

      import {HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpErrorResponse} from '@angular/common/http';
      import {Injectable} from '@angular/core';
      import {Observable} from 'rxjs/Observable';
      
      @Injectable()
      export class InterceptorService implements HttpInterceptor {
        intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
          if (localStorage.getItem('SignIn-Token')) {
            req = req.clone({
              setHeaders: {
                authorization: localStorage.getItem('SignIn-Token')
              }
            });
          }
          return next.handle(req).catch(err => {
            if (err instanceof HttpErrorResponse) {
              console.log('interceptor error');
              console.log(err);
              if (err.status === 401) {
                // JWT expired, can be setted to go to login
                return Observable.throw(err);
              } else {
                return Observable.throw(err);
              }
            }
          });
        }
      }
      

      如果你使用下面的代码在你的拦截器中出错,handleError 仍然可以工作:

      return next.handle(req).catch(err => {
        if (err instanceof HttpErrorResponse) {
          console.log('interceptor error');
          console.log(err);
          if (err.status === 401) {
            // JWT expired, can be setted to go to login
            return Observable.throw(err);
          }
          // here you are not return observable so, your global service get nothing of status ....
      
        }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-20
        • 2017-12-31
        • 1970-01-01
        • 2018-01-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多