1

I'm implementing an Angular 2 app which will make some API calls. I was wondering if is there anyway to make a generic error handler. For instance, I want to redirect users to the login route if the API responds with a 401 code. Is this posible?

Thanks

1 Answer 1

7

I created an http helper method which I use from all my services. That at least centralizes all the http activity through the application.

Handling error details is sometimes though - see my question here: Angular 2 http service. Get detailed error information

UPD: 2016-09-12 - Fixed remove method. Angular http service requires body to be defined. The reason this method exists - I wanted to be able to pass body as a part of delete request and Angular's method doesn't allow that.

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);
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

What happens when, for instance a component calls your JsonHttpHelper implementing its own catch function. Which will be called? Or which will be called first?
Helper will be the first but it rethrows the error so you also get it in the component.
I think it doesn't rethrows it. I implemented something like this and when the catch in the helper is called. Only the then in the caller is called unless I retrhow the error manually in the helper or better (for my case) throw something else. But this answer solves my problem. Thanks
Do you extend your Services with this Helper class or do you just call these functions from your Services?
@EmreÖztürk, Just calling it. Service inheritance was quite cumbersome.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.