Saturday, January 3, 2015

Interceptor in AngularJs : Global Session & Overlay (Preloader) handling

You may also like to see:

Every AngularJs application communicates with remote server by making http calls and get the data in form of JSON or XML from remote server and than this data will be show to users with html.

If your application need to interact with the remote HTTP server then AngularJs has $http service for you. It allows to communicate with backend remote web APIs using JSON or XMLHttpRequest.


Here is the general get call using $http service:

// Simple GET request example
$http.get('/api/url').
success(function(data, status, headers, config) {
// asynchronous callback event will be trigger
// when the call to URL is successful.
}).
error(function(data, status, headers, config) {
// asynchronous callback event will be trigger
// when en error occurred calling URL or server returns
// response with error status.
});
post call using $http service:
// Simple POST request example
$http.post('/api/url', {data:'hello! Its post call data!'}).
success(function(data, status, headers, config) {
// asynchronous callback event will be trigger
// when the call to URL is successful.
}).
error(function(data, status, headers, config) {
// asynchronous callback event will be trigger
// when en error occurred calling URL or server returns
// response with error status.
});

There are many scenarios when you need to capture and make some changes to each request for example you want to insert session token to each web request for the authorization similarly you may need to capture each response to perform some actions on data like global error handling for API calls Interceptors are created for these scenarios.

Interceptors


$httpProvider contains an array of registered interceptors. Interceptor is an AngularJs factory, you can register it by pushing to httpProvider interceptor array in your application configurations.

There are four different interceptors you can handle, and these four functions should be in your interceptor factory if you need to perform custom operations in it:
  1. Request Interceptor:

    A request interceptor will be invoke on each request initialization, you can change request data here like adding authorization token.
  2. Response Interceptor:

    A response interceptor will be invoke on each response from remote server, you can manipulate response here like checking pushing some data to response perform some operations on response values.
  3. Request Error Interceptor:

    A request error interceptor will be invoke if there is some error while requesting remote server, like missing header or internet disconnection. Here you can validate request and resend the request to remote server.
  4. Response Error Interceptor:

    A response error interceptor will be invoke if there is error on backend remote calls like some unhandled exception on server. Here you can handle the request by showing proper message to user or resend the request to same url or alternate if available.

Here is the example of Interceptor factory with all above interceptor functions:

// Interceptor example for angularJs.
angular.module('app').factory('customInterceptor', ['$q', function($q) {  

var myInterceptor = {
request : request,
requestError : requestError,
response : response,
responseError : responseError
};

// On request success
request: function (config) {
   // Contains the data about the request before it is sent.
   console.log(config);

  // Return the config or wrap it in a promise if blank.
  return config || $q.when(config);
};

// On request failure
requestError: function (rejection) {
  // Contains the data about the error on the request.
  console.log(rejection);

// Return the promise rejection.
return $q.reject(rejection);
};

// On response success
response: function (response) {
  // Contains the data from the response.
  console.log(response); 

// Return the response or promise.
return response || $q.when(response);
};

// On response failture
responseError: function (rejection) {
  // Contains the data about the error.
  console.log(rejection);

// Return the promise rejection.
return $q.reject(rejection);
};

return myInterceptor;
}]);
and then register it to $httpProvider interceptor array.
angular.module('app').config(['$httpProvider', function($httpProvider) {  
   $httpProvider.interceptors.push('customInterceptor');
}]);

Examples


Authentication Token Injector


If you are using token based authentication for web APIs in which on authentication call server return you a token & this token is required for all the further calls so server. So now you need to provide this authentication token to all the request so here we can use the interceptor. For this we need request interceptor and need to insert token to request.

angular.module('app').factory('authTokenInjector', ['authenticationService', function(AuthenticationService) {  
    var authTokenInjector = {
        request: function(config) {
            if (!AuthenticationService.isAnonymus) {
                config.headers['x-session-token'] = AuthenticationService.securityToken;
            }
            return config;
        }
    };
    return authTokenInjector;
}]);


Now register it to interceptors by pushing it to $httpProvider interceptor array. After this each call will be intercepted and authToken get injected to header. It is global handling for authentication now no need to handle it for individual call.

Overlay/Pre-loader to show


You want to show overlay on your page unless all the calls gets completed. For this instead of handling it manually you can write it in interceptors and let this work for your complete application.

To achieve this you can write html on your main index page for loader:


and html:


Now write the interceptor factory, which will show the loader when call get started and hide when all the calls get executed.But As you know there are multiple calls on a page so we will use a counter which will be incremented on each request and loader will be hide when request counter is zero:
// Interceptor example for angularJs.
angular.module('app').factory('overlay', ['$q', function($q) {  

  //initialize counter
  var requestCounter=0;

  var myInterceptor = {  
     request : request,
     requestError : requestError,
     response : response,
     responseError : responseError
  };

   // On request success
   request: function (config) {

    //will be incremented on each request
    requestCounter++;

    //show loader if not visible already
    if(!$('#preloader').is(':visible')){
        $('#preloader').show();
    }

    // Return the config or wrap it in a promise if blank.
    //it is required to return else call will not work
    return config || $q.when(config);
  };

  // On request failure
  requestError: function (rejection) {

     //decrement counter as request is failed
     requestCounter--;
     hideLoaderIfNoCall();   

     // Return the promise rejection.
     return $q.reject(rejection);
  };

  // On response success
  response: function (response) {
      
     //decrement counter as request is failed
     requestCounter--;
     hideLoaderIfNoCall();

     // Return the response or promise.
     return response || $q.when(response);
  };

  // On response failture
  responseError: function (rejection) {
  

     //decrement counter as request is failed
     requestCounter--;
     hideLoaderIfNoCall();

     // Return the promise rejection.
     return $q.reject(rejection);
  };
   
  function hideLoaderIfNoCall(){
     // check if counter is zero means 
     // no request is in process
 
     // use triple equals see why http://goo.gl/2K4oTX
     if(requestCounter === 0)  
        $('#preloader').hide();        
     }

  return myInterceptor;
}]);

Summary


In this article we have seen what interceptors are,  try to explain different kinds of interceptor functions and what their usages are. We also implemented session injector example in which we intercepted request and injected auth token to each request. We also implemented example to globally handling the overlay on page while requests are in process.

Please write your feedback and suggestions in comments.

You may also like to see:

1 comment:

  1. Hi,
    I need every request send from server, Before i want check some task(internet connection is there) may that task is true means it will continue or return to stop the corresponding request.

    ReplyDelete

Life insurance policy, bank loans, software, microsoft, facebook,mortgage,policy,