Showing some kind of AJAX busy indicator is a common thing in web applications. However it is something you don't want to do with every AJAX start and end of request. First of all writing all that code would be quite tedious but more importantly the might be multiple overlapping requests ongoing at the same time. And in a case like that you only want to show the AJAX busy indicator at the first request and more importantly hide it only when the last of the requests has finished.

Fortunately AngularJS has some nice integration points allowing us to do this in a very generic fashion.

 

In the case of AngularJS the integration point we are looking for is on the $httpProvider provider. This means that every AJAX HTTP request done through the $http service, and this includes all $resource services, is captured. With AngularJS 1.2 they added the interceptors collection to the $httpProvider which gives us a nice and central point to react to each AJAX request and response.

 

The solution is simple:

   1: module.config(function ($httpProvider) {
   2:     var requests = 0;
   3:  
   4:     function show() {
   5:         requests++;
   6:         if (requests === 1){
   7:             // Start of the first request
   8:         }
   9:     }
  10:  
  11:     function hide() {
  12:         requests--;
  13:         if (requests === 0) {
  14:             // End of the last request
  15:         }
  16:     }
  17:  
  18:     $httpProvider.interceptors.push(function ($q) {
  19:         return {
  20:             'request': function (config) {
  21:                 show();
  22:                 return $q.when(config);
  23:             }, 'response': function (response) {
  24:                 hide();
  25:                 return $q.when(response);
  26:             }, 'responseError': function (rejection) {
  27:                 hide();
  28:                 return $q.reject(rejection);
  29:             }
  30:         };
  31:     });
  32: });

 

The only thing left is to decide what to do in the show() and hide() functions. One good solution would be to use the $rootScope and notify the other parts of the application using $broadcast().

 

Enjoy!


Blog Post by: Maurice