目的
现有多个异步请求,需要并发请求,并限制并发数。
测试方法
let request = (delay, id) => {
return new Promise((resolve) => {
setTimeout(resolve, delay, id)
})
}
let test_requests = [
request(6000, 1),
request(3000, 2),
request(4000, 3),
request(6000, 4),
request(1000, 5),
request(2000, 6),
]
Promise解法 (递归)
思路:
- 每层递归都往 run 里加 请求
- 递归过程中,如果 run 达到临界,使用 Promise.race 来触发 递归。
- 请求的 回调为从 run 中删除 自身
- 递归终点是 所有的 request 都已经加完,返回 resolve。此时,就像盗梦空间一样,这个resolve 会不断的被返回。(此刻,请求并没有结束)。最外层会接受这个resolve,使用Promise.all 等待所有请求结束,执行回调函数。
function limitPromise(requesets = [], max = 1, callback = () => { }) {
let run = []
let next = 0
let doit = () => {
if (next === requesets.length) { // 递归终止条件
return Promise.resolve()
}
let thisRequest = requesets[next++] // 获取请求
run.push(thisRequest.then(requestRes => { // 请求推入到run数组中
console.log(requestRes)
run.splice(run.indexOf(thisRequest), 1) // 删掉自己
}))
let res = null
if (run.length === max) {
res = Promise.race(run) // 需要等待一个请求到达
}else{
res = Promise.resolve() // 不需要等待
}
return res.then(()=>doit()) // 向下递归
}
doit().then(() => {
// 此时 run 里的请求还没结束
Promise.all(run).then(() => callback())
})
}
limitPromise(test_requests, 3, () => console.log("requeset end"))
升级版:使用async、await
递归算法都有迭代写法。实际上这个题目,使用迭代更好理解。 这里使用await语法来实现 run 满的等待。 await promise 会暂停函数执行,直到 promise 成功。 这里的逻辑非常简单,就是便利请求数组,把它们加到run 中。但是,由于max的存在,需要在 run.length === max 时,使用await等待,race 到达。同样,添加完后,需要等待 run 里所有请求结束,然后执行回调函数。
async function limitAsync(requesets = [], max = 1, callback = () => { }) {
let run = [], i = 0;
for (const request of requesets) { // 数组遍历
run.push(request.then((requesetRes) => { // 依次 推入到 run
console.log(requesetRes)
run.splice(run.indexOf(request), 1)
}))
if (run.length === max) {
console.log('wait')
await Promise.race(run) // 等待 race 到达。
}
}
Promise.all(run).then(() => callback())
}
limitAsync(test_requests, 3, () => console.log("requeset end"))
创作不易!如果对你有帮助,还请点赞收藏。 如果有疑惑可以在下方留言。 如果有什么建议,可以私信我。