[实现一个批量请求函数

要求:

  1. 批量请求函数,最大并发数 maxNum
  2. 每当有一个请求返回,就留下一个空位,可以增加新的请求
  3. 所有请求完成后,结果按照 urls 里面的顺序依次发出。
const requestQueue = (maxNum = 6) => {
  const queue = []
  let current = 0
  let resolvedCount = 0
  let dequeueing = false
 
  const dequeue = () => {
    if (dequeueing) return
    dequeueing = true
    while (current < maxNum && queue.length > 0) {
      current++
      const currentPromise = queue.shift()
      currentPromise()
        .then(() => {
          console.log('请求执行成功')
        })
        .catch((error) => {
          console.error('请求执行失败:', error)
        })
        .finally(() => {
          current--
          resolvedCount++
          if (queue.length === 0 && current === 0) {
            resolveQueue()
          } else if (queue.length > 0) {
            dequeue()
          }
          dequeueing = false
        })
    }
  }
 
  const enqueue = (promiseFunc) => {
    queue.push(promiseFunc)
    if (queue.length === maxNum && !dequeueing) {
      dequeue()
    }
  }
 
  let resolveQueueCallback
  let rejectQueueCallback
 
  const queueEmptyPromise = new Promise((resolve, reject) => {
    resolveQueueCallback = resolve
    rejectQueueCallback = reject
  })
 
  const resolveQueue = () => {
    if (typeof resolveQueueCallback === 'function') {
      resolveQueueCallback(`所有请求已完成,共处理了 ${resolvedCount} 个请求。`)
      resolveQueueCallback = null // 清除回调,防止重复调用
    }
  }
 
  const rejectQueue = (error) => {
    if (typeof rejectQueueCallback === 'function') {
      rejectQueueCallback(error)
      rejectQueueCallback = null // 清除回调,防止重复调用
    }
  }
 
  return {
    enqueue,
    queueEmptyPromise,
    rejectQueue, // 提供外部拒绝队列的接口
  }
}
 
export default requestQueue
 

这样可以满足当请求池为空时,通知外部。

为什么需要一个请求池

因为Chrome的网络线程同时最多只能执行6 个,当你批量请求的时候,会导致后续一些优先级高的请求被阻塞。](<const requestQueue = (maxNum = 6) =%3E {
const queue = []
let current = 0
let resolvedCount = 0

const dequeue = () {
while (current %3C maxNum && queue.length > 0) {
current++
const currentPromise = queue.shift()
currentPromise()
.then(() {
console.log(‘请求执行成功’)
resolvedCount++
current—
checkQueue()
})
.catch((error) {
console.error(‘请求执行失败:’, error)
// rejectQueue(error)
current—
checkQueue()
})
}
}

const enqueue = (promiseFunc) {
queue.push(promiseFunc)
if (queue.length maxNum) {
dequeue()
}
}

const checkQueue = () {
if (queue.length = 0 && current = 0) {
resolveQueue()
} else if (queue.length > 0 && current < maxNum) {
dequeue()
}
}

let resolveQueueCallback
let rejectQueueCallback

const queueEmptyPromise = new Promise((resolve, reject) {
resolveQueueCallback = resolve
rejectQueueCallback = reject
})

const resolveQueue = () {
if (typeof resolveQueueCallback === ‘function’) {
resolveQueueCallback(resolvedCount)
resolveQueueCallback = null // 清除回调,防止重复调用
}
}

const rejectQueue = (error) {
if (typeof rejectQueueCallback === ‘function’) {
rejectQueueCallback(error)
rejectQueueCallback = null // 清除回调,防止重复调用
}
}

return {
enqueue,
queueEmptyPromise,
rejectQueue, // 提供外部拒绝队列的接口
}
}

export default requestQueue>)