簡體   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