我需要下载大约5万个网页,从中获取一些数据并将其放入变量。
我把每个请求都包装成承诺,然后Promise.all()
它们。我使用Request
库。
简化代码:
const request = require('request');
const urls = [url1, url2, ...];
const promises = [];
urls.forEach(url => {
promises.push((resolve, reject) => {
request(url, (error, response, body) => {
if(error){ reject(error); return; }
// do something with page
resolve(someData);
});
});
});
Promise.all(promises.map(pr => new Promise(pr)))
.then((someDataArray)=>{ /* process data /* });
但我收到
ENFILE
异常,它表示系统中打开的文件太多(在我的桌面上,打开的文件的最大数量是2048个)。我知道承诺是靠创造来实现的,但我不能解决这个问题。
也许还有别的办法?
谢谢你的回复。
最佳答案
您需要的是启动n个请求,然后在一个请求完成时启动一个新的请求(无论是否成功)。
有很多这样的库,但是能够自己实现这种限制是很重要的:
const request = require('request');
const urls = [url1, url2, ...];
const MAX_QUERIES = 10;
var remaining = urls.length;
const promises = [];
function startQuery(url){
if (!url) return;
request(url, (error, response, body) => {
if (error) // handle error
else // handle result
startQuery(urls.shift());
if (--remaining==0) return allFinished();
});
}
for (var i=0; i<MAX_QUERIES; i++) startQuery(urls.shift());
function allFinished(){
// all done
}