题目:
请实现如下函数,可以批量请求数据,所有的 url 地址在 urls 参数中,同时可以通过 max 参数控制请求的并发数,当所有请求结束之后,需要执行 callback 回调函数,发送请求的函数可以直接使用 fetch 即可
小白陷阱
题中有一个关键词“并发”,对于我这种前端小白第一次解答这道题目就掉入陷阱了, 解成了并行,?
概念解析
说到并发我们可以先来理解‘串行’,‘并行’,‘并发’这三个概念
复制代码
- 串行 当前任务执行完之后,才能执行下一个任务
- 并行 多任务同时进行,互不影响
- 并发 多任务在同一时间间隔发生
举个例子来帮助我们更好的理解:比如一个人洗衣服跟烧菜
- 串行就是: 你只能先做其中的某一件事,做完之后才能去做下一件事情
- 并行就是: 你右手烧菜,左手洗衣服同时进行
- 并发就是: 你一会儿烧菜,一会儿又去洗衣服
到这里相信大家对上述的三个概念有了一点了解,接下里我们就来实现上面这道面试题:
试题实现
<script type="text/javascript">
let bodyElement = document.body
let urls = [
'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2580986389,1527418707&fm=27&gp=0.jpg',
'https://ss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=1995874357,4132437942&fm=27&gp=0.jpg',
'https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2640393967,721831803&fm=27&gp=0.jpg',
'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1548525155,1032715394&fm=27&gp=0.jpg',
'https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=2434600655,2612296260&fm=27&gp=0.jpg',
'https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=2160840192,133594931&fm=27&gp=0.jpg'
]
let max = 2
let callback = () => {
console.log('所有请求完成了')
}
class Concurrent {
constructor(urls, max, callback) {
this.urls = urls
this.max = max
this.callback = callback
this.currentIndex = 0
}
addQueue() {
for(let i = 0, len = this.urls.length; i < len; i++) {
if (this.currentIndex < this.max) {
this.request()
break
}
this.currentIndex++
}
}
request() {
let tiemout = Math.random() * 1000
fetch(this.urls[this.currentIndex])
.then(res => res.blob())
.then(res => {
let src = URL.createObjectURL(res)
bodyElement.innerHTML += `<img src=${src} />`
})
.catch(fail => {
})
.finally(() => {
if (++this.currentIndex < this.urls.length) {
// 用延时器是因为反应接口太快 以便于观察
return setTimeout(() => {
this.request()
}, tiemout)
}
this.callback()
})
}
}
function sendRequest(urls, max, callback) {
let concurrent = new Concurrent(urls, max, callback)
concurrent.addQueue()
}
sendRequest(urls, max, callback)
</script>
复制代码
谢谢大家的阅读,有错误之处,敬请指教。