Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 : HTTP error handling

I am trying to reproduce the following behaviour that I successfully implemented using Angular 1.x interceptors and promises, in a Angular2 based Ionic2 app :

  1. Intercept HTTP request errors
  2. If the status code is 401, then

    a. make another request to register the client. This will provide some token that I can subsequently attach to each request.

    b. Retry the orignal request and provide the result to the caller through the promise / observable

  3. If the error status is anything other than 401 just let the flow normally to the caller

NB: The register process does not need any intervention from the user (no login) so I want it to be completely transparent for the user. I register once when the app is first loaded, but the session will eventually expire and I need to automatically re-register.

This is the original Angular 1 implementation (I include only the responseErrorpart of the interceptor):

responseError : function(rejection){
    if(rejection.status == 401){
        $log.info('Intercepting unauthorized 401 response. Will try to re-register the session and retry the request.');

        var security = $injector.get('SecurityService');
        var $http = $injector.get('$http');

        return security.registerSession().then(function(){
            return $http(rejection.config);
        });

    }else{
        return rejection;
    }
}

Now, I have wrapped Angular2's HTTP service and I can do simple things like adding a header to each request. However I am struggling to reproduce the same behaviour using Angular2 and Observables.

My attempt so far, this is the request method of my HTTP wrapper that my services will call :

request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {

    let req: Request = this.buildRequest(url, options);

    this.beforeCall(req);

    var observable = this.http
        .request(req)
        .retry(3)
        .catch(res => {
            debugger;
            console.log("ERROR! " + res.status);
            if(res.status == 401){
                this.logger.log('Unauthorized request. Trying to register the session and then retry the request.');
                return this.securityService.registerSession().subscribe(() => {
                    // What to do here so the client gets the result of the original request ??
                });
            }
        })
        .do((res:Response) => { this.afterCall(req, res) });

    return observable;
}
like image 374
Pierre Henry Avatar asked Apr 14 '16 16:04

Pierre Henry


People also ask

How will you handle errors in angular 2 applications?

Angular 2 applications have the option of error handling. This is done by including the ReactJS catch library and then using the catch function. Let's see the code required for error handling. This code can be added on top of the chapter for CRUD operations using http.

How you can handle errors in Angular?

One traditional way of handling errors in Angular is to provide an ErrorHandler class. This class can be extended to create your own global error handler. This is also a useful way to handle all errors that occur, but is mostly useful for tracking error logs.

What is Httperrorresponse?

HttpErrorResponselink A response that represents an error or failure, either from a non-successful HTTP status, an error while executing the request, or some other failure which occurred during the parsing of the response.


1 Answers

You could execute again the request after initialize the session using the flatMap operator of observables:

    var observable = this.http
        .request(req)
        .retry(3)
        .catch(res => {
            debugger;
            console.log("ERROR! " + res.status);
            if(res.status == 401){
                this.logger.log('Unauthorized request. Trying to register the session and then retry the request.');
                return this.securityService.registerSession().flatMap(() => {
                  return this.http.request(req); // <--------
                });
            }
        })
        .do((res:Response) => { this.afterCall(req, res) });

    return observable;
}
like image 146
Thierry Templier Avatar answered Oct 19 '22 05:10

Thierry Templier