最近在玩node爬虫的时候,发现爬的网站做了反爬处理,请求频率过高时,直接给我返回错误的结果。所以需要一个并发控制器,控制同时请求的数量,最好还能控制请求时间间隔
直接上代码
/**
*
* @param {Object} options
* @param {Number} options.limit 并发个数
* @param {Number} options.sleepTimeout 间隔时长,默认为0
*/
function Scheduler({
limit,
sleepTimeout = 0
}) {
this.list = []
this.maxLimit = limit;
this.parallelNum = 0;
this.add = function (fn) {
this.list.push(fn)
}
this.taskStart = function () {
for (var i = 0; i < this.maxLimit; i++) {
this.request()
}
}
// sleep函数用来控制请求间隔
this.sleep = async function (timeout = sleepTimeout) {
return new Promise((resolve, reject) => setTimeout(resolve, timeout))
}
this.request = async function () {
if (!this.list.length || this.parallelNum >= this.maxLimit) return
this.parallelNum++;
console.log('当前并发数', this.parallelNum);
try {
// 利用await将异步任务写成同步形式
await this.list.shift()();
await this.sleep()
} catch (error) {
console.log('error', error);
} finally {
this.parallelNum--
// 递归调用
this.request()
}
}
}
复制代码
使用
// 定义一个请求函数
function fetchFn (params, timeout = 1000) {
console.log('params', params);
return new Promise(resolve => {
setTimeout(() => {
resolve(params)
}, timeout)
})
}
// 初始化
const scheduler = new Scheduler({
limit: 4
})
const arr = [
{params: 1, timeout: 1000},
{params: 2, timeout: 700},
{params: 3, timeout: 3000},
{params: 4, timeout: 100},
{params: 5, timeout: 1000},
{params: 6, timeout: 400},
{params: 7, timeout: 2000}
]
// 添加请求函数到scheduler的列表
arr.forEach(el => {
scheduler.add(() => fetchFn(el.params, el.timeout))
})
// 开始执行并发任务
scheduler.taskStart()
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END