场景举例:图片或文件批量下载(重点是并发,同时调接口)
实现:利用Promise模拟任务队列,从而实现请求池效果。
大致原理:先进先出,在第一个已进入任务完成后,第(队列数量限制数量+1) 个任务才会进入请求池,push一个的同时就会有一个被shift
废话不多说源码如下
import axios from 'axios'
export const handQueue = (
reqs // 请求总数
) => {
reqs = reqs || []
const requestQueue = (concurrency) => {
concurrency = concurrency || 6 // 最大并发数
const queue = [] // 请求池
let current = 0
const dequeue = () => {//递归函数,当前并发级别执行请求
//它检查当前计数是否小于最大并发级别(concurrency),
//以及是否还有待处理的请求在 queue 数组中。
//如果两个条件都满足,则增加 current 计数
//从 queue 数组中取出一个请求 promise 工厂,使用 .then() 和 .catch() 执行它
//并在最后减少 current 计数,并递归调用自身以处理下一个请求。
while (current < concurrency && queue.length) {
current++;
const requestPromiseFactory = queue.shift() // 出列
requestPromiseFactory()
.then(() => { // 成功的请求逻辑
})
.catch(error => { // 失败
console.log(error)
})
.finally(() => {
current--
dequeue()
});
}
}
return (requestPromiseFactory) => {
queue.push(requestPromiseFactory) // 入队
dequeue()
}
}
const enqueue = requestQueue(6)//将请求添加到请求队列中,并控制并发请求数量为最多 6 个。
for (let i = 0; i < reqs.length; i++) {
//for 循环遍历 reqs 数组中的每个元素,使用索引 i 进行迭代。
enqueue(() => axios.get('/api/test' + i))
}
}