Add queueing to angulars $http service

Here is my solution for that: http://plnkr.co/edit/Tmjw0MCfSbBSgWRhFvcg

The idea is: each run of service add request to queue and return promise. When request to $http is finished resolve/refuse returned promise and execute next task from queue if any.

app.factory('srv', function($q,$http) {

  var queue=[];
  var execNext = function() {
    var task = queue[0];
    $http(task.c).then(function(data) {
      queue.shift();
      task.d.resolve(data);
      if (queue.length>0) execNext();
    }, function(err) {
      queue.shift();
      task.d.reject(err);
      if (queue.length>0) execNext();
    })
    ;
  }; 
  return function(config) {
    var d = $q.defer();
    queue.push({c:config,d:d});
    if (queue.length===1) execNext();            
    return d.promise;
  };
});

Looks quite simple :)


Richard: Your code works perfect but it also works with inner request like template or $templateProviders.

Here is solution to work only with external http requests

/**
 * Interceptor to queue HTTP requests.
 */
$httpProvider.interceptors.push(['$q', function ($q) {
    var _queue = [];

    /**
     * Executes the top function on the queue (if any).
     */
    function _executeTop() {
        if (_queue.length === 0) {
            return;
        }
        _queue[0]();
    }

    return {
        /**
         * Blocks each request on the queue. If the first request, processes immediately.
         */
        request: function (config) {
            if (config.url.substring(0, 4) == 'http') {
                var deferred = $q.defer();
                _queue.push(function () {
                    deferred.resolve(config);
                });
                if (_queue.length === 1) {
                    _executeTop();
                }
                return deferred.promise;
            } else {
                return config;
            }
        },
        /**
         * After each response completes, unblocks the next request.
         */
        response: function (response) {
            if (response.config.url.substring(0, 4) == 'http') {
                _queue.shift();
                _executeTop();
            }
            return response;
        },
        /**
         * After each response errors, unblocks the next request.
         */
        responseError: function (responseError) {
            if (responseError.config.url.substring(0, 4) == 'http') {
                _queue.shift();
                _executeTop();
            }
            return $q.reject(responseError);
        },
    };
}]);

Tags:

Angularjs