当需要查询1000w个url的时候,想多线程发送,但是不想同时一次性查询。
🕒 一次性查询
var http = require("http");
var totalUrl = 10000000;
for( var i = 0; i < totalUrl; i++ ) {
getUrl(i);
}
function getUrl(idToFetch){
var options = {
host: 'www.mywebsite.com',
port: 80,
path: '/page.php?id='+idToFetch,
agent: false,
pageId: idToFetch
};
http.get(options, function(res) {
var pageData = "";
res.resume();
res.on('data', function (chunk) {
if(res.statusCode == 200){
pageData +=chunk;
}
});
res.on('end', function() {
console.log("finish to fetch id: "+options.pageId);
// do something with the HTML page
});
}).on('error', function(e) {
console.log("Error: " + options.host + "\n" + e.message);
});
}
🚀控制promise并发
Promise.race
可以接收一个promise数组并,在其中第一个promise返回的时候返回。通过这个我们就可以控制并发的promise数量。
/**
* promise 并发处理 控制最大请求数
* @param factory promise工厂 返回非Promise对象表示结束
* @param maxRun 最大并发数
* @param promises promise数组 缓存正在运行的promise
* @param startIndex 开始的索引 默认从0 开始
* @returns {Promise}
*/
function promiseMax(factory, maxRun, promises, startIndex) {
if (!Array.isArray(promises)) {
promises = [];
}
if (startIndex === undefined) {
startIndex = 0;
}
while (promises.length < maxRun) {
let pro = factory(startIndex++);
if (pro instanceof Promise) {
pro = pro.then(v => {
promises.splice(promises.indexOf(pro), 1);
return v;
});
promises.push(pro);
} else {
return Promise.all(promises);
}
}
return Promise.race(promises).then(() => {
return promiseMax(factory, maxRun, promises, startIndex)
});
}
✈️并发请求
通过promiseMax
第二个参数可以很容易控制并发数量。
promiseMax((idToFetch) => {
if (idToFetch >= 10000000) return false;
return new Promise((resolve, reject) => {
var options = {
host: 'www.mywebsite.com',
port: 80,
path: '/page.php?id=' + idToFetch,
agent: false,
pageId: idToFetch
};
http.get(options, function (res) {
var pageData = "";
res.resume();
res.on('data', function (chunk) {
if (res.statusCode == 200) {
pageData += chunk;
}
});
res.on('end', function () {
console.log("finish to fetch id: " + options.pageId);
resolve();
});
}).on('error', function (e) {
console.log("Error: " + options.host + "\n" + e.message);
reject(e);
});
});
}, 10).then(() => {
console.info('end');
});