写一个并发控制器

最近在玩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
喜欢就支持一下吧
点赞0 分享