前不久做了字节青训营的笔试,其中第二道编程题便是利用promise.all()实现对并发请求个数的限制。
场景需求大概就是假设目前有邮件20封,每次只能发5封,五封邮件发出的时间有长有短,如果有一封右键发送完成后,就从剩下的15封邮件内再拿出一封放入请求队列中。
也就是直到所有邮件发送完成前,promise.all()函数中一直有5封邮件。
现使用定时器模拟发送请求的函数
function asyncFetch(param) {
return new Promise((resolve) => {
setTimeout(() => {
resolve(param)
}, 2000)
})
}
function limitRequest(requests, limit) {
const pool = [] //正处于请求中的函数
let index = 0 //待请求函数数组的索引
const requestQueue = Math.min(requests.length, limit) //判断请求队列和个数的大小
for (let key = 0; key < requestQueue; key++) {
pool.push(run(requests[index++]))
}
function awaitRequest() {
if (index == requests.length - 1) {
console.log("所有请求已进入promise.all");
return Promise.resolve()
}
return run(requests[index++])
}
function run(request) {
return asyncFetch(request).then(awaitRequest) //每完成一个请求,就执行resolve回调,从而向请求队列中添加新的请求
}
Promise.all(pool).then(() => {
console.log("请求已全部完成");
})
}
const paramArr=[1,2,3,4,5,6,7,8,9]
limitRequest(paramArr, 3);