如何在angular $ http服务中优先处理请求?

时间:2015-02-11 09:14:45

标签: angularjs angular-http angular-http-interceptors

我正在使用大量延迟数据加载的应用程序。我想根据优先级'来优先处理http请求。 PARAM。

这是使用它的概念。

$http.get(url, {params: query, priority: 1})

我在考虑使用$ http拦截器。这样的事情:

 angular.module('myModule')
.factory('httpPriorityInterceptor', function ($interval, $q) {
    var requestStack = [];

    return {
        request: function (config) {

            config.priority = config.priority || 3;

            requestStack.push(config);
            requestStack.sort(sortByPriority);

            if (isFirstToGo(item)) return requestStack.pop();

            deferred = $q.defer();

            var intervalPromise = $interval(function(){

                if (isFirstToGo(item)) {
                    deferred.resolve(requestStack.pop());
                    $interval.cancel(intervalPromise);
                };

            }, 100);

            return deferred.promise;

        }   
    };
});

但我不能在这里回复承诺。有任何想法吗?

3 个答案:

答案 0 :(得分:5)

您可以通过使用$http的超时属性来执行此操作,并使用requestresponseError回调来保存和执行每个$http个请求分别

步骤:

  1. $http回调过程中懒惰地注入request服务,这将是获得$http服务的唯一方法,因为它在工厂注入了#{1}}服务函数导致循环依赖。

  2. 确定是否已处理request回调中传递的配置。如果尚未处理,则在请求堆栈中添加配置并按优先级对其进行排序。在配置对象的timeout属性中添加已解析的promise,以取消当前的$http请求。最后返回配置对象。

  3. 取消$http请求后,请在responseError回调中抓住该请求。如果请求堆栈中有项目,则弹出第一项(config)并使用延迟加载的$http服务调用它。最后使用回调提供的拒绝参数返回被拒绝的承诺。

  4. DEMO

    angular.module('demo', [])
    
      .config(function($httpProvider) {
        $httpProvider.interceptors.push('httpPriorityInterceptor');
      })
    
      .factory('httpPriorityInterceptor', function($q, $injector) {
    
    
        var requestStack = [], // request stack
            $http = null; // http service to be lazy loaded
    
        return {
          request: request, // request callback
          responseError: responseError // responseError callback
        };
    
        // comparison function to sort request stack priority
        function sort(config1, config2) {
          return config1.priority < config2.priority;
        }
    
        function request(config) {
    
          // Lazy load $http service
          if(!$http) {
            $http = $injector.get('$http');
          }
    
          // check if configuration has not been requested
          if(!config.hasBeenRequested) {
    
            // set indicator that configuration has been requested
            config.hasBeenRequested = true;
    
            // set default priority if not present
            config.priority = config.priority || 3;
    
            // add a copy of the configuration
            // to prevent it from copying the timeout property
            requestStack.push(angular.copy(config));
    
            // sort each configuration by priority
            requestStack = requestStack.sort(sort);
    
            // cancel request by adding a resolved promise
            config.timeout = $q.when();
          }
    
          // return config
          return config;
        }
    
    
        function responseError(rejection) {
    
          // check if there are requests to be processed
          if(requestStack.length > 0) {
    
            // pop the top most priority
            var config = requestStack.pop();
            console.log(config);
    
            // process the configuration
            $http(config);
          }
    
          // return rejected request
          return $q.reject(rejection);
        }
    
      })
    
      .run(function($http) {
    
        // create http request
        var createRequest = function(priority) {
          $http.get('/priority/' + priority, {priority: priority});
        };
    
        createRequest(3);
        createRequest(1);
        createRequest(4);
        createRequest(2);
    
      });
    

    要确保以正确的顺序调用每个请求,您可以检查控制台选项卡中的日志或网络选项卡中的请求。

    <强>更新

    如果您希望按顺序调用请求(当第一个请求必须在下一个请求调用之前完成时),那么您可以在responseError回调中调整我的解决方案,如下所示:

    <强> DEMO

    function responseError(rejection) {
    
      // check if there are requests to be processed
      if(requestStack.length > 0) {
    
        requestStack.reduceRight(function(promise, config) {
          return promise.finally(function() {
            return $http(config);
          });
        }, $q.when());
    
        requestStack.length = 0;
    
      }
    
      // return rejected request
      return $q.reject(rejection);
    }
    

答案 1 :(得分:1)

尝试包裹你的超时

var deferred = $q.defer();
       (function (_deferred){
        var intervalPromise = $interval(function(){

            if (isFirstToGo(item)) {
                _defferred.resolve(requestStack.pop());
                $interval.cancel(intervalPromise);
            };

        }, 100);
        })(deferred);
return deferred.promise;

好像它在$ interval上迷路了。你的延迟是例如全球范围之前设置var

答案 2 :(得分:0)

这不是正确的解决方案。您可以通过编写自己的服务来确定api调用队列的优先级,然后再调用http get。

这不适用于以下用例 Angular Http Priority