NodeJSasynchronous队列速度太快(asynchronous队列方法减速)

我有一个HTTP Get请求,我想分析响应并将其保存到我的数据库。

如果我叫爬行(我)独立我得到好的结果。 但是我必须从1到2000调用crawl()。我得到了很好的结果,但是有些响应似乎会丢失,有些响应是重复的。 我不认为我知道如何调用数千个asynchronous函数。 我正在使用asynchronous模块队列function,但到目前为止,我仍然缺less一些数据,仍然有一些重复。 我在这里做错了什么? 谢谢你的帮助。

我在爬行

我的节点function:

function getOptions(i) { return { host: 'magicseaweed.com', path: '/syndicate/rss/index.php?id='+i+'&unit=uk', method: 'GET' } }; function crawl(i){ var req = http.request(getOptions(i), function(res) { res.on('data', function (body) { parseLocation(body); }); }); req.end(); } function parseLocation(body){ parser.parseString(body, function(err, result) { if(result && typeof result.rss != 'undefined') { var locationTitle = result.rss.channel[0].title; var locationString = result.rss.channel[0].item[0].link[0]; var location = new Location({ id: locationString.split('/')[2], name: locationTitle }); location.save(); } }); } N = 2 //# of simultaneous tasks var q = async.queue(function (task, callback) { crawl(task.url); callback(); }, N); q.drain = function() { console.log('Crawling done.'); } for(var i = 0; i < 100; i++){ q.push({url: 'http://magicseaweed.com/syndicate/rss/index.php?id='+i+'&unit=uk'}); } 

[编辑]好吧,经过大量的testing,似乎我所抓取的服务无法处理如此之多的请求。 因为当我按顺序做每个请求,我可以得到所有的好回应。

有没有一种方法来减慢ASYNC队列方法?

你应该看看这个伟大的模块, asynchronous ,这简化了这样的asynchronous任务。 你可以使用队列,简单的例子:

 N = # of simultaneous tasks var q = async.queue(function (task, callback) { somehttprequestfunction(task.url, function(){ callback(); } }, N); q.drain = function() { console.log('all items have been processed'); } for(var i = 0; i < 2000; i++){ q.push({url:"http://somewebsite.com/"+i+"/feed/"}); } 

如果你只调用callback函数,将会有一个正在进行的动作的窗口,任务空间将可用于将来的任务。 不同的是,你的代码现在打开2000连接,显然失败率很高。 将其限制在一个合理的值,5,10,20(取决于现场和连接)将导致更好的成功率。 如果请求失败,则可以再次尝试,或者将任务推送到另一个asynchronous队列以进行另一个试用。 关键是在队列函数中调用callback(),这样一个房间完成后就可以使用了。

 var q = async.queue(function (task, callback) { crawl(task.url); callback(); }, N); 

在开始前一个任务之后,你马上执行下一个任务,这样队列就没有意义了。 你应该像这样修改你的代码:

 // first, modify your 'crawl' function to take a callback argument, and call this callback after the job is done. // then var q = async.queue(function (task, next/* name this argument as 'next' is more meaningful */) { crawl(task.url, function () { // after this one is done, start next one. next(); }); // or, more simple way, crawl(task.url, next); }, N); 

另一种select,如果你想。 香草JS没有花哨的图书馆。

 var incrementer = 0; var resultsArray = []; var myInterval = setInterval(function() { incrementer++ if(incrementer == 100){ clearInterval(myInterval) //when done parse results array } //make request here //push request result to array here }, 500); 

每半秒调用一次该function。 简单的方法来强制同步并在x请求后退出。

我知道我对这个问题有点晚了,但是这里是我写的一个解决scheme,当使用节点4或节点5testingapi端点时,要减慢请求数量:

 var fs = require('fs'); var supertest = require('supertest'); var request = supertest("http://sometesturl.com/api/test/v1/") var Helper = require('./check.helper'); var basicAuth = Helper.basicAuth; var options = Helper.options; fs.readFile('test.txt', function(err, data){ var parsedItems = JSON.parse(data); var urlparts = [] // create a queue for (let year of range(1975, 2016)) { for (var make in parsedItems[year]){ console.log(year, make, '/models/' + year + '/' + make) urlparts.push({urlpart:'/models/' + year + '/' + make, year: year, make: make}) } } // start dequeue waitDequeue(); // This function calls itself after the makeRequest promise completes function waitDequeue(){ var item = urlparts.pop() if (item){ makeRequest(item) .then(function(){ // wait this time before next dequeue setTimeout(function() { waitDequeue(); }, 3000); }) } else { write(parsedItems) } } // make a request, mutate parsedItems then resolve function makeRequest(item){ return new Promise((resolve, reject)=>{ request .get(item.urlpart) .set(options.auth[0], options.auth[1]) .set(options.type[0], options.type[1]) .end(function(err, res) { if (err) return done1(err); console.log(res.body) res.body.forEach(function(model){ parsedItems[item.year][item.make][model] = {} }); resolve() }) }) } // write the results back to the file function write(parsedItems){ fs.writeFile('test.txt', JSON.stringify(parsedItems, null, 4), function(err){ console.log(err) }) } }) 

有点晚,但我发现这个作品! 使用asynchronous你可以减慢队列的使用,而在任务处理程序内,例如:

 var q = async.priorityQueue(function(task, callback) { // your code process here for each task //when ready to complete the task delay it by calling async.whilst( //wait 6 seconds function() { return count < 10; }, function(callback) { count++; setTimeout(function() { callback(null, count); }, 1000); }, function (err, n) { // n seconds have passed callback(); //callback to q handler } ); //whilst } , 5);