开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
练习一些 JS 等手写的实现,是前端进阶的一种很好的方法,手写(或是手敲)可以帮助我们更好的了解实现原理,包括一些面试也经常会出现关于原理或是手写的题目。
那么,什么是限制并发数量呢?举个例子:去景区排队买票,一共有三个窗口,每当有人买完离开后,下一个人才能开始卖票,即一次最多三个人同时买票。如下图:
在代码中,当有很多个接口的时候,如果同时调用,可能会造成请求阻塞的问题,轻则页面卡顿,重则服务器崩溃 。所以为了避免这样的问题发生,优化性能,可以进行多请求的并发限制。
在这里,我们使用 setTimeout(...) 来模拟异步的代码
代码实现
思路:
- 循环执行运行函数,循环的次数控制在最大并发数
- shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值(shift()会改变数组的长度,这样就相当于执行一个移除一个,移除数组末尾的元素可以使用 pop() 方法)。
- 待执行的数组中还存在函数,继续执行,当有一个执行完,继续执行下一个(递归)
const promiseGenerator = (num) => {
return new Array(num)
.fill(0)
.map((item, index) => () =>
new Promise((resolve, reject) => {
setTimeout(() => {
console.log(index+1)
resolve(index)
}, 1000)
})
)
}
const PromiseLimit = (allArr, limit) => {
if(!Array.isArray(allArr)) throw new Error("不是数组类型")
function run() {
if(allArr.length) {
allArr.shift()().then(res=>{
allArr.length && run()
})
}
}
for(let i=0;i<limit;i++) {
run()
}
}
const proArr = promiseGenerator(8)
PromiseLimit(proArr,5)
运行结果
当设定 1000 ms的执行时间时,可以看到前五个先执行,被控制并发的后面的几个再依次执行
注:一定要记得判断数组的长度和限制数量limit的大小关系,如果实际要执行的数组长度 < 限制的数量,不做判断会报错(TypeError: allArr.shift(...) is not a function)