处理HTTP全局服务错误角4.3,handleError,401,0等,拦截器,jwt,头

处理HTTP全局服务错误角4.3,handleError,401,0等,拦截器,jwt,头

问题描述:

我有一个http全局服务,它被称为所有服务;所以我可以通过实例进行最佳管理;错误,警报,变量等。处理HTTP全局服务错误角4.3,handleError,401,0等,拦截器,jwt,头

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

} 

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

前角4.3我有可观的,我可以有捕获错误,并在组件中的全局服务,子服务中抛出一个observable。现在,它不工作,我不知道如何管理渔获物,并处理好与观测

误差在新的角度指南: 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}`); 
     } 
    } 
    }); 

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

我终于找到一个解决方案,错误的对象,所以在角4.3之前,错误对象是一个响应,现在它的HttpErrorResponse,无论如何,我们得到的对象,所以我们可以要求属性。大多数函数不考虑错误状态0,o当服务器不工作时,或者角4.3中的拦截器或您在错误管理中执行的任何操作都不会产生正确的状态时,什么也不做。

我发现的最终解决方案只是简单地向错误对象请求对象属性,并且在不希望显示已知错误的后端错误的情况下,我可以定义消息错误。

寻找环境。TS文件(角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'} 
    } 
}; 

然后处理错误全球服务可以是:

在你的拦截器

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

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

,如果你做了错误在你的拦截器中用下面的代码举例,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 .... 

    } 
}); 

定义了严格的类型如下错误的情况下,

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

仍然有可观你基本上可以保留现有的组件代码。所有你需要改变的是使用新的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); 
}