Общий обработчик ошибок ответа Angular 2 Http

Я реализую приложение Angular 2, которое будет выполнять некоторые вызовы API. Мне было интересно, есть ли способ сделать общий обработчик ошибок. Например, я хочу перенаправить пользователей на маршрут входа, если API отвечает кодом 401. Это возможно?

Спасибо


person Javier Enríquez    schedule 10.09.2016    source источник


Ответы (1)


Я создал вспомогательный метод http, который использую во всех своих службах. Это, по крайней мере, централизует всю активность http через приложение.

Однако иногда обработка деталей ошибок - см. Мой вопрос здесь: https://stackoverflow.com/questions/38936384/angular-2-http-service-get-detailed-error-information

UPD: 2016-09-12 - Исправлен метод remove. Служба Angular http требует определения тела. Причина существования этого метода - я хотел передать тело как часть запроса delete, а метод Angular не позволяет этого.

import {Injectable} from '@angular/core';
import {Http, Request, Response, Headers, RequestOptionsArgs, RequestMethod} from "@angular/http";
import {RequestArgs} from "@angular/http/src/interfaces";
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class JsonHttpHelper {
    protected headers: Headers;

    constructor(private _http: Http) {
        this.headers = new Headers();
        this.headers.append('Content-Type', 'application/json');
        this.headers.append('Accept', 'application/json');
    }

    get(url:string) : Observable<any> {
        return this._http.get(url)
            .map((res: Response) => res.json())
            .catch(this.handleError);
    }

    post(url:string, data:any, args?: RequestOptionsArgs) : Observable<any> {
        if (args == null) args = {};
        if (args.headers === undefined) args.headers = this.headers;

        return this._http.post(url, JSON.stringify(data), args)
            .map((res: Response) => JsonHttpHelper.json(res))
            .catch(this.handleError);
    }

    put(url:string, data:any, args?: RequestOptionsArgs) : Observable<any> {
        if (args == null) args = {};
        if (args.headers === undefined) args.headers = this.headers;

        return this._http.put(url, JSON.stringify(data), args)
            .map((res: Response) => JsonHttpHelper.json(res))
            .catch(this.handleError);
    }

    remove(url: string, data?: any, args?: RequestOptionsArgs): Observable<any> {
        if (args == null) args = {};

        args.url = url;
        args.method = RequestMethod.Delete;
        if (!args.headers) args.headers = this.headers;
        args.body  = data ? JSON.stringify(data) : null;

        return this._http.request(new Request(<RequestArgs>args))
            .map((res: Response) => JsonHttpHelper.json(res))
            .catch(this.handleError);
    }

    private static json(res: Response): any {
        return res.text() === "" ? res : res.json();
    }

    private handleError(error:any) {
        console.error(error);
        return Observable.throw(error);

        // The following doesn't work.
        // There's no error status at least in case of network errors.
        // WHY?!
        //
        // if ( error === undefined) error = null;
        // let errMsg = (error && error.message)
        //     ? error.message
        //     : (error && error.status)
        //         ? `${error.status} - ${error.statusText}`
        //         : error;
        //
        // return Observable.throw(errMsg);
    }
}
person rook    schedule 10.09.2016
comment
Что происходит, когда, например, компонент вызывает вашу JsonHttpHelper, реализующую свою собственную функцию catch. Какой будет называться? Или что будет вызвано первым? - person Javier Enríquez; 10.09.2016
comment
Помощник будет первым, но он повторно выдаст ошибку, поэтому вы также получите ее в компоненте. - person rook; 10.09.2016
comment
Я думаю, что он не выбрасывает его. Я реализовал что-то подобное, и когда вызывается catch в помощнике. Вызывается только then в вызывающем объекте, если только я не повторю ошибку вручную в помощнике или лучше (в моем случае) не выкину что-то еще. Но этот ответ решает мою проблему. Спасибо - person Javier Enríquez; 11.09.2016
comment
Вы расширяете свои службы с помощью этого вспомогательного класса или просто вызываете эти функции из своих служб? - person Emre Öztürk; 19.03.2017
comment
@EmreÖztürk, просто звоню. Наследование службы было довольно громоздким. - person rook; 19.03.2017
comment
Я попробовал ваше решение, сначала оно выглядело работающим, но, в конце концов, я обнаружил, что на самом деле оно не выдает ошибку. Observable.throw(error) не был передан обработчику ошибок подписчика, странно - person fifth; 23.06.2017