前端实现并发数量控制

138 阅读1分钟

众所周知,浏览器会限制同一域名下的并发请求数量,最大并发数一般是6~8个,因此前端针对并发数量做控制,避免请求数量过大

完整代码如下

// 前端控制请求并发数
const asyncQueue = (maxCount) => {
  // 异步任务队列
  const queue = []
  // 正在进行的异步任务数量
  let activeCount = 0
  // 执行下一个异步任务
  const next = () => {
    // 活跃任务数量-1
    activeCount--
    // 队列不为空,执行下一个任务
    if(queue.length > 0) {
      queue.shift()()
    }
  }
  // 执行异步任务
  const run = async (fn, resolve, ...args) => {
    // 活跃任务数量+1
    activeCount++
    // 执行异步任务
    const result = fn(...args)
    // 改变promise状态
    resolve(result)
    try {
      // 等待任务执行完成
      await result
    } catch {}
    // 进行下一个异步任务
    next()
  }
  // 添加任务到队列
  const addQueue = (fn, resolve, ...args) => {
    // 入队
    queue.push(run.bind(null, fn, resolve, ...args))
    // 没有达到并发上线时,立即执行
    if (activeCount < maxCount && queue.length > 0) {
      queue.shift()()
    }
  }
  const generator = (fn, ...args) => {
    return new Promise((resolve) => {
      addQueue(fn, resolve, ...args)
    })
  }
  return generator
}

测试代码

const queue = asyncQueue(2);
function asyncFun(value, delay) {
  return new Promise((resolve) => {
    console.log('start ' + value);
    setTimeout(() => resolve(value), delay);
  });
}
const arr = [
  queue(() => asyncFun('aaa', 2000)),
  queue(() => asyncFun('bbb', 3000)),
  queue(() => asyncFun('ccc', 2000)),
  queue(() => asyncFun('ddd', 2000)),
  queue(() => asyncFun('eee', 2000))
];
const result = await Promise.all(arr);
console.log(result);