当前位置: 首页 > 面试题库 >

如何在有角$ http服务中确定请求的优先级?

萧献
2023-03-14
问题内容

我正在处理具有大量惰性数据加载的应用程序。我想根据“优先级”参数对HTTP请求进行优先级排序。

这就是使用它的概念。

$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;

        }   
    };
});

但是我不能在这里退还诺言。有任何想法吗?


问题答案:

您可以通过使用$http的timeout属性来做到这一点,并使用requestresponseError回调$http分别保存和执行每个请求。

脚步:

  1. 延迟地$httprequest回调过程中注入服务,这将是获得$http服务的唯一方法,因为在工厂函数中注入服务会导致循环依赖。

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

  3. 一旦$http请求已经被取消了,抓住它的responseError回调。如果请求堆栈中有项目,请弹出第一个项目(配置),然后使用延迟加载的$http服务调用它。最后,使用回调提供的拒绝参数返回拒绝的承诺。

演示

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回调中的解决方案调整为以下内容:

演示

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);
}

更新06/16/2019

如评论中所述,优先请求返回的承诺不会返回预期的承诺解决方案或拒绝。我已经通过以下方式更新了拦截器以适应这种情况:

  1. 保存相对于每个http配置的延迟承诺。
  2. responseError为了保持解决或拒绝请求的目的,在拦截器中返回延迟的诺言。
  3. 最后,在优先级请求的迭代中使用延迟的promise。

演示

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 defered promise relative to the config requested
        config.$$defer = $q.defer();

        // 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) {

        requestStack.reduceRight(function(promise, config) {
          var defer = config.$$defer;
          delete config.$$defer;
          return promise.finally(function() {
            return $http(config)
              .then(function(response) {
                defer.resolve(response);
              })
              .catch(function(error) {
                defer.reject(error);
              });

          });
        }, $q.when());

        requestStack.length = 0;

      }

      return rejection.config.$$defer.promise;
    }

  })

  .run(function($http) {

    // create http request
    var createRequest = function(priority) {
      return $http.get(priority + '.json', {priority: priority});
    };

    createRequest(3);
    createRequest(1).then(function(data) { console.log(data); })
    createRequest(4);
    createRequest(2);

  });


 类似资料:
  • 我是web服务新手,正在阅读Martin Kalin的《Java Webservices》一书。我已经了解了它最初的基本概念,有一个问题: 假设将HTTP请求(包含SOAP消息信封)发送到JavaWeb服务()。该请求是否由Servlet内部处理,Servlet提取SOAP消息并将其转换为相应Java域对象,然后调用服务实现bean? 无论Metro和Axis等现成框架如何,这个问题都是通用的。只

  • Python 的标准库 urllib 提供了大部分 HTTP 功能,但使用起来较繁琐。通常,我们会使用另外一个优秀的第三方库:Requests,它的标语是:Requests: HTTP for Humans。 Requests 提供了很多功能特性,几乎涵盖了当今 Web 服务的需求,比如: 浏览器式的 SSL 验证 身份认证 Keep-Alive & 连接池 带持久 Cookie 的会话 流下载

  • 我在AnyLogic中开发了货运领域的离散事件模型。我有一个名为“truck”的代理,我在其页面和命令中定义了一个名为“冰箱”的参数

  • 问题内容: 我正在读一本书,叫做《 Pro Angular JS》。但是,我有一个关于如何捕获错误状态的问题。 我编码的是: 如果我编写代码“ console.log($ scope.data.error.status);” ,为什么console.log的参数未定义? 这本书中有一句话,“传递给错误函数的对象定义了状态和消息属性。” 所以我做了$ scope.data.error.status

  • 我有一个带有RESTAPI的Java服务。从客户端一次可以发送多个请求,我希望通过API在服务器端一次实现一个请求。问题是我需要在服务器端对请求进行优先级排序。换句话说,如果一次发送10个请求,我需要使用优先级队列一次对所有10个请求设置优先级,并根据优先级选择一个请求。可以从同一个客户端或多个客户端发送请求。 现在,在上面的代码中,一次可以为一个请求执行这个。 有什么解决办法吗?我见过一些多线程

  • 我只需要在文档中的三个字段中搜索一个术语,并根据搜索术语的位置对结果进行排序。例如,找到3个文档:1个在字段2中有搜索词,2个在字段3中有搜索词,3个在字段1中有搜索词。 我想按顺序看:3、1、2。 我以为我可以用助推来做。现在我使用以下方法: 然而,它似乎是,如果我有一个文档与4个词等于搜索词在字段2和另一个文档与1个词在字段1,比后者将有一个较小的分数。 我看到的一个解决方案是为field1和