还是老样子先说说需求,如果有100个请求,如何使用Promise控制数量为为n最大并发
主要思路
以这张图为例,此时的最大并发数量为3,我们 从urls中取出三个url,依次发送请求,无论请求的结果是成功或者失败,依次按照顺序放入results中,当完成一个请求,从urls中取出下一个url地址,直至全部取出
function concurRequest(urls, maxNum) {
return new Promise((resolve) => {
if (urls.length === 0) {
resolve([])
return
}
const results = []
function request() {}
})
}
完成过程
1、我们使用index规定为下次发送url的下标
2、将请求成功/失败结果按照顺序放入resluts中,i用来记录每次的位置
3、当一个请求完成,发送下一个请求
tip:这里连续三次使用request来模拟并发数量为3,后续解决maxNum的问题
const results = []
let index = 0 //下一个请求的下标
async function request() {
const i = index
const url = urls[index]
index++
try {
const resp = await axios(url)
//resp加入results
results[i] = resp
} catch (err) {
//err加入results
results[i] = err
} finally {
request()
}
}
request()
request()
request()
4、此时会遇到一个问题,在发送完所有请求后,urls会出现越界问题,这里需要限制一下 5、判断是否已经全部请求完成,设置count,在finally中说明已经完成一个请求,比较count和数组长度
async function request() {
if (index === urls.length) {
return
}
const i = index
const url = urls[index]
index++
try {
const resp = await fetch(url)
results[i] = resp
} catch (err) {
results[i] = err
} finally {
count++
if (count === urls.length) {
console.log('over')
resolve(results)
}
request()
request()
request()
}
}
6、最后处理一下maxNum最大并发数量的问题,最大并发数量为n,我们就需要发送n个request,这里直接套一个循环即可
7、当urls的长度小于maxNum,这里我们需要取最小值
const times = Math.min(maxNum, urls.length)
for (let i = 0; i < times; i++) {
request()
}
完整代码
/**
* 并发请求
* @param{string[]} 待urls请求的 url数组
* @param{number} maxNum最大并发数
*/
function concurRequest(urls, maxNum) {
return new Promise((resolve) => {
if (urls.length === 0) {
resolve([])
return
}
const results = []
let index = 0 //下一个请求的下标
let count = 0 //当前请求完成的数量
async function request() {
if (index === urls.length) {
return
}
const i = index
const url = urls[index]
index++
try {
const resp = await axios(url)
results[i] = resp
} catch (err) {
results[i] = err
} finally {
count++
if (count === urls.length) {
console.log('over')
resolve(results)
}
request()
}
}
const times = Math.min(maxNum, urls.length)
for (let i = 0; i < times; i++) {
request()
}
})
}