asyncPool应用场景
一个不太常见的极端场景,当我们为了某个操作需要发生异步请求的时候,等待所有异步请求都完成时进行某些操作。这个时候我们不在简简单单的发送 1 - 2 个请求而是 5 - 10个(其实极端场景式 很多很多个请求,这个打个比喻更容易理解)。
通常情况下我们通过 promise.all 可以保证多个请求完成后进行操作,等待所有的promise
对象都达到了resovle再执行then方法进行操作。这样是可以完成的,但是当我们发送1000个请求,等待1000个请求完成后在进行操作,首先不说等待完成操作,就简简单单的http请求瞬间发生1000个,你猜浏览器会怎么样?只能说友谊的小船说翻就翻,因为瞬间发出大量的http
请求,导致浏览器堆积了很多栈,导致内存溢出。
并发控制孕育而生,如何实现思路?
身为开发者我们无法控制http请求的多少,但是我们能控制异步任务的数量,具体来说就是我们可以控制promise的实例化数量,用以避免高并发带来的问题。当我们想要的(数量自己输入)promise的数量全部resolve的时候,再将其他的promise放入队列。
直接放代码进行解释:
async function asyncPool(poolLimit = 1,array = [] , interatorFn ){
const result = [];
const executing = [];
for(let item in array){
// 生成一个 promise 实例,并在 then 方法中的 onFullfilled 函数里返回实际要执行的 promise,
const promise = interatorFn(item);
result.push(promise);
const e = promise.then(()=>{
// 将执行完毕的 promise 移除
executing.splice(executing.indexOf(e),1)
})
executing.push(e)
if(poolLimit >= array.length){
await Promise.race(executing);
}
}
}
return Promise.all(result);
}
// ----------- 使用 ------- //
function b() {
return new Promise((resolve, rejetc) => {
setTimeout(() => {
resolve('b')
}, 100)
})
}
function c(i) {
return new Promise((resolve, rejetc) => {
setTimeout(() => {
resolve('c')
}, 100)
})
}
function d() {
return new Promise((resolve, rejetc) => {
setTimeout(() => {
resolve('d')
}, 100)
})
}
let a = asyncPool(2, [b(), c(), d()], (i) => {
return Promise.resolve(i);
});
a.then(res => {
console.log(res)
})