2017-10-07 127 views
0

這是一個寫入節點js的網頁抓取代碼。
當隊列有足夠的url時,這段代碼是否總是保持5個併發請求?
爲什麼控制檯顯示其他內容?
限制併發操作nodejs

var request = require("request"); 
var cheerio = require("cheerio"); 
var fs = require('fs'); 

var concurrent_requests = 0; 
var queue = []; 
var baseUrl = "https://angularjs.org/"; 

function makeApiCall(url){ 
    if(url) { 
     queue.unshift(url); 
    } 
    if(concurrent_requests<5) { 
     var nextUrl = queue.pop(); 
     if(nextUrl) { 
      concurrent_requests++; 
      request(nextUrl, function (error, response, body) { 
       var invalidUrl; 
       concurrent_requests--; 
       if(body) { 
        var $ = cheerio.load(body); 
        var anchors = $("a"); 
        var data = ""; 
        for (var i = 0; i < anchors.length; i++) { 
         url = $(anchors[i]).attr("href"); 
         if(!url || url === "#" || url === "javascript:void(0)"){ 
          invalidUrl = true; 
         } 
         else{ 
          invalidUrl = false; 
         } 

         if (!invalidUrl) { 
          makeApiCall(url); 
          data += url + ", " + nextUrl + "\n"; 
         } 
        } 
        //console.log(data); 
        fs.appendFile('urls.csv',data, function (err) { 
         if (err) throw err; 
        }); 
       } 
       else{ 
        makeApiCall(); 
       } 
      }); 
     } 
    } 
    console.log(concurrent_requests); 

} 


makeApiCall(baseUrl); 
+1

循環它只會有一次一個請求。 –

+0

你能澄清一下嗎? –

+0

檢查答案 –

回答

1

Becoz,你有一個國家不與if語句要求超過5條件。

如果(concurrent_requests < 5){

該解決方案是不是具有可擴展性會超過一定的遞歸調用後的堆棧結構。

希望它有幫助。

+0

你能澄清一下嗎? –

1

您正在使用if條件來檢查併發 請求的計數是否小於5。但請記住它是if聲明, 不循環。這意味着它只會被調用一次。

您正在對您的功能makeApiCall進行遞歸調用 請求的回調。當請求被滿足時,請求的回調僅運行 。

考慮到以上兩點,在你的if條件中,你檢查concurrent_requests<5然後你調用request方法,並且你的程序是理想的。在請求標識滿足的某個時間之後,請求的回調將會運行,在某些邏輯之後再次調用makeApiCall。因此,在每次調用中,您只需調用一次請求,然後等待解決,然後只有您的程序繼續進行下一個請求。

如果你想併發請求,然後使用類似這樣的

function makeApiCall(url){ 
    if(url) { 
     queue.unshift(url); 
    } 
    // Use a loop here 
    while(concurrent_requests<5) { 
     var nextUrl = queue.pop(); 
     if(nextUrl) { 
      concurrent_requests++; 
      request(nextUrl, function (error, response, body) { 
       var invalidUrl; 
       concurrent_requests--; 
       if(body) { 
         ... 
         if (!invalidUrl) { 
          makeApiCall(url); 
          data += url + ", " + nextUrl + "\n"; 
         } 
        } 
        ... 
       } 
       else{ 
        makeApiCall(); 
       } 
      }); 
     } 
     else{ 
      // Remember to break out of loop when queue is empty to avoid infinite loop. 
      break; 
     } 
    } 
    console.log(concurrent_requests); 

}