2

I'm developing an angular app that makes multiple ajax request.

I would like to timeout a request if there are 10 already active request, so I should never have more than 10 active request.

How can I make this? is there similar to ajaxStart() method in angularJs?

Or I should make a global var with $window and add or delete the ajax requests?

@Mike P Something like this:

$http.post("/foo/bar", requestData,
    transformRequest: transform
})

transform = function(data){
    if($window.counter > 10){
        setTimeout(1000);
    }else{
        return data;    
    }
}
Tropicalista
  • 3,097
  • 12
  • 44
  • 72
  • When you say timeout a request - do you mean defer it or do you mean not let it happen? – Mike Pugh May 29 '13 at 02:22
  • I mean defer a request – Tropicalista May 29 '13 at 02:26
  • Ok - I removed the throw exception from my example. You'd essentially want to read the data and header info, and store that in an array on the service. Then on the response transform, you can either broadcast some event to let code elsewhere re-fire the $http requests, or you could inject $http into the service itself and have it re-fire those requests, popping them off of the array. – Mike Pugh May 29 '13 at 02:43
  • I don't understand this: You'd essentially want to read the data and header info – Tropicalista May 29 '13 at 03:17

2 Answers2

3

AngularJS 1.1.5 (this is considered the unstable release) provides support for both request and response interceptors. The concepts are pretty similar to what's being done via the angular-http-auth interceptor module (https://github.com/witoldsz/angular-http-auth)

The following http-throttler service can be injected into your code to throttle your HTTP requests. Wire it into Angular when you define your app.

Example:

angular.module('myApp', ['http-throttler'])
       .config(['$routeProvider','$httpProvider', function($routeProvider, $httpProvider) {
                 $httpProvider.interceptors.push('httpThrottler');
                 $routeProvider.
                        when('.............your stuff here..........')
                        ...........more of your stuff....
       });

Put this in http-interceptor.js and include it in your application.

(function() {
   "use strict";  angular.module('http-throttler', ['http-interceptor-buffer']).factory("httpThrottler", ['$q', '$log', 'httpBuffer', function($q, $log, httpBuffer) {
  var reqCount, service;

  reqCount = 0;
  service = {
    request: function(config) {
      var deferred;

      $log.info("Incoming Request - current count = " + reqCount);
      if (reqCount >= 10) {
        $log.warn("Too many requests");
        deferred = $q.defer();
        httpBuffer.append(config, deferred);
        return deferred.promise;
      } else {
        reqCount++;
        return config || $q.when(config);
      }
    },
    response: function(response) {
      $log.info("Response received from server");
      reqCount--;
      httpBuffer.retryOne();
      return response || $q.when(response);
    }
  };
  return service;
}
]);

  angular.module('http-interceptor-buffer', []).factory('httpBuffer', [
'$log', function($log) {
  var buffer, retryHttpRequest, service;

  buffer = [];
  retryHttpRequest = function(config, deferred) {
    if (config != null) {
      $log.info("Resolving config promise");
      return deferred.resolve(config);
    }
  };
  service = {
    append: function(config, deferred) {
      return buffer.push({
        config: config,
        deferred: deferred
      });
    },
    retryOne: function() {
      var req;

      if (buffer.length > 0) {
        req = buffer.pop();
        return retryHttpRequest(req.config, req.deferred);
      }
    }
  };
     return service;
   }
 ]);

}).call(this);

Above, it's hard coded to 10 per your question. I may make this configurable and push it up on GitHub in case others find it useful.

Again - this does not work in the 1.0.7 release of AngularJS, since 1.0.7 does not support the new interceptors array on $httpProvider. It only supports responseInterceptors. I haven't tried 1.1.4, but this appears to work reasonably well in 1.1.5.

Code available on GitHub @ https://github.com/mikepugh/angular-http-throttler

Mike Pugh
  • 6,787
  • 2
  • 27
  • 25
  • It's not clear how I should transform the request. Please, could you explain better? – Tropicalista May 29 '13 at 01:11
  • I have edited my question: could you tell me if this is the correct approach? – Tropicalista May 29 '13 at 01:53
  • I got this error: Error: Unknown provider: $httpProviderProvider <- $httpProvider <- ajaxLimiter – Tropicalista May 29 '13 at 03:08
  • I've updated the code with a working solution that you should be able to drop into your angular app as a service. – Mike Pugh May 29 '13 at 16:09
  • This is a good answer. Unfortunately I'm on 1.0.7 of Angular...My solution will be create a global variable and check if is greater than 10, then stop requests. I will switch soon on 1.1.5 and then I will use your approach...Thanks – Tropicalista May 29 '13 at 22:22
0

You can use jquery $.ajax with angularjs. You can use the following jQuery functions :

The number of active requests: jQuery.active function

To get notified when this number changes:

http://api.jquery.com/ajaxStart/

http://api.jquery.com/ajaxStop/

Community
  • 1
  • 1
basarat
  • 261,912
  • 58
  • 460
  • 511