2017-08-04 88 views
2

我有一個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}`); 
     } 
    } 
    }); 

現在管理這個的正確方法是什麼?

回答

1

我終於找到一個解決方案,錯誤的對象,所以在角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 .... 

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

仍然有可觀你基本上可以保留現有的組件代碼。所有你需要改變的是使用新的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); 
}