以角度限制同步异步$ http get请求

时间:2015-08-10 14:49:47

标签: javascript ajax angularjs

我有一个页面,其中包含连接到媒体流的IP地址表。我将它们链接到包含位置信息的数据库,并且能够从缓存提供重复的ips请求以减少负载。但是,当一次发出太多请求时,页面崩溃并给出Error: Insufficient Resources。我尝试使用this进行批处理,但我收到了关于Synchronous XMLHttpRequest on main thread的弃用警告,但无论如何它都没有帮助。如何限制一次完成的搜索次数?我不想一次限制它们,因为否则会花费太长时间。以下是相关代码:

angular.forEach($scope.results, function(conn, key){

    $http.get("addrinfo.cgi?action=get&addr="+conn.ip, { cache: true}) //$scope.results is list of ip addresses
                    .then(function(ipLocation) {
                        console.log(ipLocation);
                        var locationResults = ipLocation.data; 
                        conn.country = locationResults.country;
                        //... more assignments
                    });
                });

编辑:我在实施保罗答案时遇到了问题。继续获得RequestManager is undefined代码结构如下所示。

angular.module('ip-module', [
'app.controller',
'app.filter',
'app.factory'
]);

app.controller('ip-analysis', function($scope, $http, $q) { ... })

.filter('customNumFilter', function() { ... })

.factory('RequestManager', ['$http', '$scope', function() { ... 
}]);

1 个答案:

答案 0 :(得分:3)

您可以创建一个处理请求的经理。管理员可以跟踪正在运行的请求数,一旦达到限制,就将多余的请求重定向到队列中。请求完成后,如果有足够的插槽,则可以选择并运行队列中的下一个请求。

import copy

angular.module('your-module', []) 

.controller('Controller1', function(){
  .... 
}) 

.controller('Controller1', function(){
  .... 
})

.factory('RequestManager', function(){
  var manager = {
    limit: 10,
    queue: [],
    cache: {},
    requests: 0,
    sendRequest: function(conn){
      if(manager.requests < manager.limit){
        if conn.ip in manager.cache.keys():
          conn.update(manager.cache[conn.ip])
        else:
          manager.runRequest(conn);
      }else{
        manager.queue.push(conn);
      }
    },
    runRequest: function(conn){
      manager.requests++;
      $http.get("addrinfo.cgi?action=get&addr="+conn.ip, { cache: true})
        .then(function(ipLocation) {
            console.log(ipLocation);
            var locationResults = ipLocation.data; 
            conn.country = locationResults.country;
            //... more assignments
            manager.cache[conn.ip] = copy.deepcopy(conn) #use deepcopy to make sure the value is not overwritten in the $scope
            runNextRequest();
        }, function(error){
          runNextRequest();
        });
    },
    runNextRequest: function(){
      if(manager.requests > 0){
        manager.requests --;
        if(queue.length > 0){
          manager.runRequest(queue.shift());
        }
      }
    }
  }
  return manager;
}

在您的控制器中,您可以执行类似

的操作
angular.forEach($scope.results, function(conn, key){
  RequestManager.sendRequest(conn);
}

我不完全确定您如何使用这些值,但您可以调整代码以更恰当地使用它们。

免责声明:我没有时间运行此代码,因此请注意可能的错误。