【问题标题】:Meteor / Node.js: Multiple http requests within a for loop, evenly across a timed interval?Meteor / Node.js:for循环内的多个http请求,均匀地跨越一个时间间隔?
【发布时间】:2023-03-11 20:07:01
【问题描述】:

亲爱的 JS 开发人员 -

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

每个 http 请求之间有两个参数会发生变化,这些变化的值存储在两个单独的数组中。我没有详细说明每个 http 请求(如果计算两个数组之间的所有组合,则为 20*4=80),而是在 for 循环中编写了一个 for 循环,以极大地整合代码。对于每个响应,如果返回正常,则两个 switch 语句通过评估其 iy 值来处理应如何处理响应。

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

希望有人能提供一些指导,告诉我我可以采取哪些不同的方法来解决这个问题,因为我已经束手无策了。

附:我尝试使用递归方法执行此操作,但出现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);

【问题讨论】:

  • 迭代器 iy 的作用域仅限于它们所在的函数,而不是 for 循环。按照说明here

标签: javascript node.js asynchronous callback meteor


【解决方案1】:

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

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

【讨论】:

  • 我的代码在服务器端运行,所以没有 DOM 交互。你能澄清一下你的意思吗?
  • 我误解了你的问题。但我认为可以使用相同的方法。如果这个条件是: if (request.statusCode == 200 || array1.indexOf[array1[i]]!=i || array2.indexOf[array2[y]]!=y) 你不会执行错误的语句如果这些值之前已被修改。
【解决方案2】:
for (i=0;i<array1.length;i++)

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

经验法则: 始终使用 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 指的是在 for 块之外的变量 y,当您定义的每个函数具有时,该变量已经增加到 10被调用。所以console.log(y) 总是解析为console.log(10)

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

【讨论】:

  • 感谢您的回复!我添加了 var 声明并将函数(和数组)移出循环,但似乎仍然存在由 i 和 y 值引起的污染。这是我的循环的console.log(i+" "+y+" "+response) 输出,仅适用于 i=0 和 y=0:&gt; 0 0 617.51&gt; 0 0 617.51&gt; 0 0 34.3&gt; 0 0 617.51&gt; 0 0 617.51&gt; 0 0 617.51617.51 是预期的。注意分散在两者之间的 34.3 值(i>0 响应)。关于为什么程序认为对应于不同 i 值的 34.3 值是 i=0 的任何指导?
  • 想通了 - 如此简单。我没有将响应传递给 updates() 函数,因此 HTTP 请求延迟可能会导致它处理错误的响应。感谢您提供有关将函数移出循环的提示!
猜你喜欢
  • 2014-08-22
  • 1970-01-01
  • 2020-10-09
  • 2022-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多