2017-05-04 70 views
0

親愛的互聯網幫助人員, 我開始編寫HTTP隊列。我有一個請求類,其中工作,如果我使用它沒有上下文,但與我的隊列活躍,我的http請求將無法正常工作。我無法弄清楚爲什麼。執行延遲HTTP請求的NodeJS隊列很奇怪

var t = new Request('s','s', function(){}); 
t.perform(); 

當我在任何文件中執行這樣的請求。有用。但是,當我用我的隊列(index.js,L19到L22)沒有執行任何請求。功能Request.perform()已執行,但HTTP請求不在那裏。 對不起,我的英語,我不是本地人^^

index.js

const http = require('http'); 
const https = require('https'); 
const {Request} = require('./classes/Request'); 
const queue = require('./queue.js'); 

queue.setCallbackFunction(performRequest); 
function performRequest(request){ 
    console.log("2"); 
    request.perform(); 
} 
var req = new Request('','', function(response,body){ 
    console.log(JSON.stringify(response) + " :: " + body); 
}); 
queue.add(req); 

queue.js

var queue = []; 
var ratelimits = []; 

module.exports.add = function(request){ 
    queue.push(request); 
    run_queue(); 
} 
module.exports.setCallbackFunction = function(cb){ 
    call = cb; 
} 
module.exports.setRateLimits = function(ratelimitings){ 
    ratelimits = []; 
    for(var z in ratelimitings){ 
     var x = ratelimitings[z]; 
     var data = {}; 
     data.max = x[0]; 
     data.time = x[1]; 
     data.count = 0; 

     ratelimits[x[1]] = data; 
    } 
} 
function run_queue(){ 
    var q; 
    if(queue.length > 0){ 
     q = run_request(queue[0]); 
     while (q == true) { 
      queue.shift(); 
      if(queue.length > 0) 
      q = run_request(queue[0]); 
     } 
    } 
} 

function run_request(request){ 
    for(var z in ratelimits){ 
     var x = ratelimits[z]; 
     if(x.max <= x.count){ 
      return false; 
     } 
    } 
    for(var z in ratelimits){ 
     var x = ratelimits[z]; 
     if(x.count === 0){ 
      setTimeout(function(z){ 
       console.log(JSON.stringify(x)); 
       ratelimits[z].count = 0; 
       run_queue(); 
      },z,z); 
     } 
     x.count++; 
     //console.log(JSON.stringify(x)); 
    } 
    //DO REQUEST 
    console.log("1") 
    call(request); 
    return true; 
} 

Request.js

exports.Request = class{ 
    constructor(host,path,cb){ 
     this.path = path; 
     this.cb = cb; 
     this.host = host 
    } 
    perform(){ 
     console.log("3"); 
     var https = require('https'); 
     var options = { 
      host: 'www.example.com', 
      path: '/' 
     }; 

     var callback = function(response) { 
     //HERE THIS GETS NEVER CALLED BECAUSE OF WHATEVER WHILE ITS IN THE QUEUE 
      var str = ''; 
     //another chunk of data has been recieved, so append it to `str` 
      response.on('data', function (chunk) { 
       str += chunk; 
      }); 

      //the whole response has been recieved, so we just print it out here 
      response.on('end', function() { 
       console.log(str); 
      }); 
     } 

     https.request(options, callback).end(); 
    } 
} 

打印所有3個console.logs,但請求回調從不被調用。

run_request()
function run_queue(){ 
    var q; 
    if(queue.length > 0){ 
     q = run_request(queue[0]); 
     while (q == true) { 
      queue.shift(); 
      if(queue.length > 0) 
      q = run_request(queue[0]); 
     } 
    } 
} 

之後執行成功(HTTP請求被髮送),queue.shift()立即調用,這意味着剛添加到隊列中的req對象從移除:

回答

0

問題是由函數run_queue引起queue數組並且符合垃圾收集條件。由於一個HTTP請求/響應通常花費幾毫秒,所以在檢索響應之前很有可能req對象被GCed(銷燬)。因此,不會調用回調,因爲HTTP連接不再存在。

要改變隊列,但保持從GC req對象,您需要將其保存在其他地方,比如一個臨時數組(無限循環bug在下面的代碼也修復):

var tmp = []; 
function run_queue(){ 
    var q; 
    if(queue.length > 0){ 
     q = run_request(queue[0]); 
     while (q == true) { 
      tmp.push(queue.shift()); 
      if(queue.length > 0) { 
       q = run_request(queue[0]); 
      } else { 
       q = false; 
      } 
     } 
    } 
} 

請注意以上代碼僅供演示使用。在生產代碼中,您需要管理tmp陣列 - 當一個請求完成時,需要從tmp中刪除。否則,tmp陣列將繼續增長...

+0

謝謝!我會試試這個。聽起來很符合我的邏輯。 – qry

+0

@qry是你的問題解決? – shaochuancs

+0

不...不行...抱歉。但是,謝謝你的幫助 – qry