2017-10-07 120 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); 

}