繁体   English   中英

流星/ Node.js:在for循环中均匀地跨越一个定时间隔发出多个http请求?

[英]Meteor / Node.js: Multiple http requests within a for loop, evenly across a timed interval?

尊敬的JS开发人员-

我正在尝试按一定时间间隔在Meteor应用程序中发出一批服务器端http请求,并根据收到的响应对MongoDB数据库进行更新。 每隔15秒,应开始一批请求,并且该组请求应在15秒内平均分配(而不是一次淹没API服务器)。 为了平均分配请求,我尝试使用setTimeout方法。

每个http请求之间有两个参数更改,这些不同的值存储在两个单独的数组中。 而不是拼出每个HTTP请求(如果您计算两个数组之间的所有组合,即20 * 4 = 80),而是在for循环内编写了一个for循环,以极大地整合代码。 对于每个响应,如果返回正常,则两个switch语句通过评估其iy值来处理应如何处理响应。

问题:我似乎处于“回调地狱”中。 当响应从服务器到达时,循环系统有时已经将i和/或y的值增加了,因此我不能100%地确定使用switch语句来处理响应。 最后, updatedb()函数对错误的响应进行了某些计算(将它们存储在数据库中的错误位置)。

希望有人能为我提供一些指导,以帮助我解决问题,因为我不知所措。

PS我尝试使用递归方法执行此操作,但出现了Maximum call stack size exceeded错误。




test = function test(){
  // API base URL
  var baseURL = "https://example.com/";
  // Array1
  var array1 =  ['item1', // i = 0
                 'item2', // i = 1
                 'item3', // i = 2
                 'item4', // i = 3
                 'item5', // i = 4
                 'item6', // i = 5
                 'item7', // i = 6
                 'item8', // i = 7
                 'item9', // i = 8
                 'item10', // i = 9
                 'item11', // i = 10
                 'item12', // i = 11
                 'item13', // i = 12
                 'item14', // i = 13
                 'item15', // i = 14
                 'item16', // i = 15
                 'item17', // i = 16
                 'item18', // i = 17
                 'item19', // i = 18
                 'item20']; // i = 19
  // Array2
  var array2 = ['/path1/',   // y=0
                '/path2/',   // y=1
                '/path3/',   // y=2
                '/path4/'];  // y=3

  var count = 1;
  var timeout = Math.round(interval/(array1.length*array2.length)*count);

  // Iterate over each item in array1
  Meteor.setTimeout(function() {
    for (i=0;i<array1.length;i++) {
      // Iterate over each path in array2
      for (y=0;y<array2.length;y++) {
        var request = Meteor.http.call("GET", baseURL + array1[i] + array2[y]);
        // If response is OK, then:
        if (request.statusCode == 200) {
          // do meaningful things
          function updatedb(value) {
            switch (y) {
              case 0: /*do something with uniqueValue for case of y=0 */; break;
              // case 1, case 2, case 3
            }
          }
          switch(i) {
            case 0: updatedb(uniqueValue); break;
            // case 1, case 2, case 3, case 4, case 5...
          }
        } else {
          throw new Meteor.Error(500, "API call failed with error: " + request.status_txt);
        }
      }
    }
  }, timeout);
  count++;
}

var interval = 15000;
Meteor.setInterval(function(){
  test();
}, interval);
for (i=0;i<array1.length;i++)

这是Javascript中的致命罪恶之一。 您声明了一个全局变量i并对该全局变量进行迭代。 这样,每次迭代的循环i都将遍历SAME变量。 我不相信你想要的。

经验法则: 始终使用var关键字声明变量。

(例外:故意创建全局变量。)

for (var i=0; i<array1.length; ++i)

您的代码的第二个问题比较棘手,但幸运的是众所周知。 看下面的代码:

var funs = [];

for(var y=0; y<10; ++y) {
  var print = function() {
    console.log(y);
  }
  funs.push(print);
}

for(var i=0; i<funs.length; ++i) {
  funs[i]();
}

您希望在运行代码时将什么打印到控制台上? 想一想。 然后检查一下: http : //repl.it/Uzb

您在该页面上看到的第二个警告说明了一切: 不要在循环内创建函数 什么情况是,可变y您使用里面的函数体是指可变y作用域之外for块,这是已经递增到10每个你定义已经被调用的函数的时间。 因此console.log(y)始终解析为console.log(10)

经验法则: 不要在循环内创建函数。

您可以在调用后对元素进行更新的事件上使用事件。

例如,您可以查看http://test-this.ro/assign-the-same-tests-to-the-zephyr-suites-after-they-moved-to-another-project/第19行“ $('body')。on('requestscompleted',function(){...”

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM