【问题标题】:Limiting or delaying http requests from a AngularJS service限制或延迟来自 AngularJS 服务的 http 请求
【发布时间】:2014-06-17 09:45:44
【问题描述】:

我已经创建了一个为我的 AngularJS 应用程序提供数据的服务,它非常简单,该服务只包含许多进行 $http 调用的方法。问题是每次当我的视图中的 HTML 项目(产品详细信息的 div)在视图端口中可见(我是延迟加载)时都会进行此调用,因此用户可以直接滚动到底部页面等,并创建一些请求(通常大约 50 - 60 个),这些请求将阻止/减慢其他请求或整个应用程序的速度。因此,我需要一种方法来限制、限制、排队或延迟请求 - 排队是最好的,但目前我只是要限制/管理服务中的请求数量。

这就是我在控制器/指令中调用服务的方式:

productAvailabilityService.getAvailability(scope.productId).then(function (result) {
    // do stuff with the result... 
});

这就是服务

.factory('productAvailabilityService', function ($http) {

        var prodAv = {};  
        prodAv.getAvailability = function (productId) {           
                return $http({
                    method: 'GET',
                    url: '/api/product/getAvailability',
                    params: {
                        'productId': productId
                    }

                }).then(
                    function (response) {
                        return response;
                    }, function () {
                        return 0;
                    });
            }
        };

        return prodAv;
    });

现在我想添加限制功能......像这样:

.factory('productAvailabilityService', function ($http) {

    var prodAv = {};
    prodAv.requests = 0;

    prodAv.getAvailability = function (productId) {

        if (prodAv.requests > 6) {
            return function () {
                return 'Too many requests';
            };
        } else {

            prodAv.requests++;
            return $http({
                method: 'GET',
                url: '/api/product/:productId/getAvailability',
                params: {
                    'productId': productId
                }

            }).then(
                function (response) {
                    prodAv.requests--;
                    return response;
                }, function () {
                    prodAv.requests--;
                    return 0;
                });
        }
    };

    return prodAv;
});

当请求数大于 6 时,这会给我一个错误,.getAvailability(...).then is not a function 我似乎无法修复,任何人都可以看到我做错了什么......而且这种方法确实看起来小错误,有没有更好的方法来管理我可以调用服务/运行$http 请求的次数?提前致谢!

【问题讨论】:

  • 也许您的方法不正确。例如,您可以通过在每个请求中获取多个项目来减少请求数量。这当然会使响应更大(可能对加载时间没有明显影响),但从我看来,减少请求数量比这更重要。同时,设置某种限制无论如何都是一个好主意,但有很多方法可以实现它,具体取决于您希望它有多严格(即:您甚至可以在客户端进行)

标签: javascript angularjs


【解决方案1】:

您必须对 productAvailabilityService 使用 Promise。你返回一个函数而不是一个promise,所以“then()”在第一行代码中抛出一个错误..

这是带有承诺的代码部分:

.factory('productAvailabilityService', function ($http,$q) {

var prodAv = {};
prodAv.requests = 0;

prodAv.getAvailability = function (productId) {

    if (prodAv.requests > 6) {
        var deferred = $q.defer();
        deferred.reject("no more than 6 calls");
        return deferred.promise;
    }else{ //etc.

如果您管理延迟呼叫,您也许还可以使用 resolve 功能,

【讨论】:

  • 这是一个很好的答案,谢谢,我真的需要更好地理解承诺,但是我知道 get productAvailabilityService.getAvailability(...) 是未从控制器(不是服务)定义的
  • 我认为您的新 productAvailabilityService 源中存在语法错误,这会阻止 Angular 将其注入控制器。我没有看到错误在哪里。
  • 我看到使用console.log时返回$q.promise;是未定义的?我应该返回 return deferred.promise; 吗?
  • 一行就可以做到return $q.reject("no more than 6 calls");
【解决方案2】:

添加这个DelayHttp

app.factory('DelayHttp', ($http, $timeout) => {
    let counter = 0,
        delay = 100;

    return (conf) => {
        counter += 1;

        return $timeout(() => {
            counter -= 1;
            return $http(conf);
        }, counter * delay);
    };
});

用法:

return DelayHttp({
    url: url,
    method: 'GET',
    params: params
});

以 100 毫秒间隔或最多 10 个请求/秒对请求进行排队和执行。您可以调整延迟以匹配您所需的吞吐量。

【讨论】:

    【解决方案3】:

    我会设置一个时间间隔并等到用户到达其想要的内容,然后再发出类似的请求

     var timer;
     function getData(){
              $timeout.cancel(timer);
              timer=$timeout(function(){
                    $http.get(url)
              },200);
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 2018-03-02
      相关资源
      最近更新 更多