2017-03-29 14 views
5

모든 HTTP 요청에 대해 추가 코드를 작성할 필요없이 HTTP 요청이 실패하면 사용자에게 알려야합니다. 각도 4의 HTTP 오류에 대한 중앙 집중식 처리

나는 각 2 프로토 타입했다 :

@Injectable() 
export class MyErrorHandler extends ErrorHandler { 

    constructor() { 
    super(false); 
    } 

    handleError(error: any) { 
    this.tellUser(error); 
    super.handleError(error); 
    } 

    tellUser(error: any) { 
    // dig for the root cause 
    if (error.rejection) { 
     error = error.rejection; 
    } 
    if (error instanceof ViewWrappedError) { 
     error = error.originalError; 
    } 

    let message; 
    if (error instanceof Response) { 
     // TODO: localize and display nicely 
     const messages = { 
     0: "Could not connect to server", 
     } 
     message = messages[error.status] || ("The server reported a system error (HTTP " + error.status + ")"); 
    } else { 
     message = "A system error occurred."; 
    } 
    console.warn(message); 
    } 
} 

을하지만 ViewWrappedError는 HttpResponse에에 toString을 호출하는 덕분에,

export function viewWrappedDebugError(err: any, context: DebugContext): Error { 
    if (!(err instanceof Error)) { 
    // errors that are not Error instances don't have a stack, 
    // so it is ok to wrap them into a new Error object... 
    err = new Error(err.toString()); 
    } 
    _addDebugContext(err, context); 
    return err; 
} 

하는 각도 4에서 대체되었습니다, 그것을 만드는 상태 코드를 쿼리하기가 어렵습니다 ...

중앙 집중식 오류 처리를 위해 잘 지원되는 공개 API를 제공하기를 기대합니다. 오류 메시지를 구문 분석하는 것 외에 HTTP 오류를 중앙에서 처리 할 수있는 방법이 있습니까?

업데이트 : 구성 요소가 중앙 집중식 오류 처리를 쉽게 무시할 수있는 경우를 선호합니다.

답변

0

나는이 종류의 로직을 BaseService 내부에 집중화 한 다음 It의 모든 서비스를 상속합니다. Angular 2는 이전 버전 인 Http Interceptors을 제공하지 않으므로 이러한 종류의 물건을 다루기가 어렵습니다.

import { Injectable } from '@angular/core'; 
import { Response } from '@angular/http'; 
import { Observable } from 'rxjs/Observable'; 
import { NotificationService } from '********'; 


@Injectable() 
export class BaseService { 
    protected url: string; 
    protected http: Http; 

    constructor(http: Http, protected notification: NotificationService) { 
    this.http = http; 
    } 

    protected extractData(res: Response) { 
     // 
     // Depende do formato da response, algumas APIs retornam um objeto data e dentro deste o conteudo propriamente dito 
     // Em minhas APIs sempre retorno diretamente o objeto que desejo 
     // 
     return res.json(); 
    } 

    protected handleError(error: Response | any) { 
    let erros: string[] = []; 

    switch (error.status) { 
     case 400: 
     let res = error.json(); 

    // 
    // Depende do formato, minhas APIs sempre retornar um objeto com array errors quando tenho 400 
    // 
     for (let index = 0; index < res.errors.length; index++) { 
      let msg = res.errors[index]; 
      erros.push(msg); 
     }; 

     this.notification.showMultipleWarn(erros); 
     break; 
     case 404: 
    this.notification.showWarning('O recurso requisitado não existe.'); 
    break; 
     case 406: 
     case 409: 
     case 500: 
     this.notification.showError('Ocorreu um erro inesperado.'); 
     break; 
     default: 
     this.notification.showError('Ocorreu um erro inesperado.'); 
     break; 
    } 

    return Observable.throw(new Error(error.status)); 
    } 
} 

다음은이 덜 자세하게 처리 할 수있는 방법을 설명 내 블로그 게시물입니다 : Receitas Angular2: Interceptando erros HTTP de forma Global

게시물이 포르투갈어로 작성되어 있지만 코드는 당신에게 몇 가지 힌트를 줄 수 있습니다. 나는 지금이 거대한 프로젝트에서이 방법을 사용하고 있으며, 잘 작동합니다.

1

또 다른 옵션은 API와 상호 작용하는 데 필요한 사용자 지정 오류 처리, 디버깅 논리, 추가 헤더 등을 추가하는 동안 Http 서비스에 위임하는 서비스를 갖는 것입니다.

이 서비스는 Http와 관련된 상호 작용을위한 중앙 집중식 지점이되므로 오류 처리를 중앙 집중식으로 처리 할 수 ​​있습니다. 내가 개발하는 모든 프로젝트에서 실제로 상호 작용하는 모든 단일 API는 모든 요청에 ​​대해 발생해야하는 몇 가지 공통 구성 (기본 URL을 지정하는 것만 큼)을 갖고 있기 때문에 항상 그러한 클래스를 만듭니다. 이러한 클래스의

예 : 나에게

export class ApiGateway { 

    baseURL = "https://myapi.com"; // or sometimes pulled from another file 
    constructor(private http: Http) { } 

    get(path, params) { 
    showLoadingIndicator(); 

    let headers = this.createMySpecialHeaders(); 
    let options = { headers: headers } // and whatever else you need to generalize 
    let fullUrl = this.baseUrl + path + '?' + this.urlEncode(params)`; 
    return this.get(path, params, options) 
       .do(() => hideLoadingIndicator()) 
       .map(res => res.json()) 
       .catch(err => { 
        hideLoadingIndicator(); 
        // show error message or whatever the app does with API errors etc 
        // sometimes rethrow the error, depending on the use case 
       }) 
    } 
} 

, 이것은 기본 OOP 원칙 - 당신은 당신에게 외부의 변화로부터 보호 할 수 있도록 어댑터 클래스에서 통제 할 수없는 것들과의 상호 작용을 포장하고 필요한 경우 외부 물건의 API를 원하는 것으로 변경하십시오.

그런 클래스를 사용하면 예를 들어 각도 4로 업그레이드하고 오류를받는 방법이 변경된 경우 새 오류 기술을 처리하기 위해 한 곳만 변경할 수 있습니다.