一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
这道题也是我之前面试字节的一道题,写出来跟大家分享下。
模拟请求
因为是实例,没有真实的请求,我们利用promise和setTimeout来模拟请求的执行。
function delay(text,time){
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(text)
},time)
})
}
有2个参数,一个text来区分不同的请求,一个time表示请求的时间。
Promise.all实现
function myPromiseAll(arr){
return new Promise((resolve,reject) => {
let count = 0
const n = arr.length
const res = new Array(n)
for(let i = 0; i < n; i++){
const p = arr[i]
Promise.resolve(p()).then(result => {
res[i] = result
count++
if(count === n){
resolve(res)
}
})
}
})
}
const p1 = () => delay('1',1000)
const p2 = () => delay('2',1500)
const p3 = () => delay('3',500)
const p = [p1,p2,p3]
myPromiseAll(p).then(res => console.log(res))
实现一个普通的Promise.all很简单,关键在于要定义一个count变量,每执行完一个promise,count+1,在count等于输入数组的长度时,输出。
实现一个可以限制并发数的Primise.all
什么叫限制并发量?
限制并发量,比如说我们Promise.all(p1,p2,p3,p4,p5),限制并发量为3,每时每刻只能有3个请求,注意不是先执行完前3个请求之后,再执行后3个请求哦,是每时每刻都有3个请求执行。
const p1 = () => delay('1',5000)
const p2 = () => delay('2',2000)
const p3 = () => delay('3',3000)
const p4 = () => delay('4',2000)
const p5 = () => delay('5',3000)
const p = [p1,p2,p3,p4,p5]
我们看上面的例子, 先执行 p1 p2 p3 这三个请求,p2 最先执行完,然后执行p4, 然后是p3执行完,再执行p5
输出的结果是2,3,4,1,5; 而不是我们预想的先执行完前3个,再执行后两个
具体实现
function myPromiseAll(arr,limit){
return new Promise((resolve,reject) => {
let count = 0
const n = arr.length
const res = new Array(n)
let index = 0
function step(i){
if(count === n) {
resolve(res)
return
}
if(arr[index]){
arr[index]().then(result => {
res[i] = result
count++
step(index)
})
}
index++
}
for(let i = 0; i < limit; i++){
step(i)
}
})
}
const p1 = () => delay('1',5000)
const p2 = () => delay('2',2000)
const p3 = () => delay('3',3000)
const p4 = () => delay('4',2000)
const p5 = () => delay('5',3000)
const p = [p1,p2,p3,p4,p5]
myPromiseAll(p,3).then(res => console.log(res))
看下结果:
主要看一下几个参数,函数的参数i,来保证promise是按顺序存入res里面的。
index参数来保证promise的执行顺序。