-最近看到了一道面试题,觉得还蛮有意思,就实现了一下。面试题如下:
请实现如下的函数,可以批量请求数据,所有的URL地址在urls参数中,
同时可以通过max参数 控制请求的并发度。当所有的请求结束后,
需要执行callback回调。
发请求的函数可以直接使用fetch。
// 请实现如下的函数,可以批量请求数据,所有的URL地址在urls参数中,同时可以通过max参数 控制请求的并发度。当所有的请求结束后,需要执行callback回调。发请求的函数可以直接使用fetch。
const log = console.log.bind()
// 模拟异步url请求
function sleep(i) {
return new Promise((resolve, reject) => {
setTimeout(() => {
log(`我sleep 了${i}毫秒`)
resolve()
}, i)
})
}
// 产生a- b之间的随机数
function random(a, b) {
// floor 一个表示小于或等于指定的最大整数的数字
return a + Math.floor(Math.random() * (b - a))
}
// 异步数组
function sleepTime(n) {
let arrTime = []
for (let i = 0; i < n; i++) {
let a = random(1200, 20000)
arrTime.push(a)
}
return arrTime
}
let arr = sleepTime(10)
let max = 5
// 处理并发数量最大max 数组中所有数据处理完之后 回调 cb
let cb = () => {
log('所有的异步数据我都处理完了。。。。。')
}
function handleSleep(arr, max, cb) {
let len = arr.length
let index = 0
let sleepArr = [] // 存放异步请求数组
function doSleep() {
if (index >= len) {
log('要执行全部的sleep了', sleepArr)
Promise.all(sleepArr).then(() => {
cb()
})
} else if (index < len && sleepArr.length < max) {
// 开始往sleepArr里面push异步数据
let one = sleep(arr[index]).then(() => {
// 这个处理完了 将其踢出异步队列
sleepArr.splice(sleepArr.indexOf(one), 1)
if (sleepArr.length < max && index < len) {
// 如果此时异步数组中的长度 小于最大并发值
// 并且当前index < len (说明整个数组还没有被遍历完)
// 再次调用自身
return doSleep()
}
})
log('one', index)
sleepArr.push(one)
// 每次push进去之后都会加1 只有一个地方更改数据比较安全
index++
doSleep()
}
}
doSleep()
}
handleSleep(arr, max, cb)