如何实现并发请求控制(限制同时发起的请求数量)?
方案:维护一个执行队列
async function concurrentLimit(tasks, limit) {
const results = []
const executing = new Set()
for (const task of tasks) {
const p = task().then(result => {
executing.delete(p)
return result
})
executing.add(p)
results.push(p)
if (executing.size >= limit) {
await Promise.race(executing)
}
}
return Promise.all(results)
}
使用示例
const urls = Array.from({ length: 10 }, (_, i) => `/api/${i}`)
const tasks = urls.map(url => () =>
fetch(url).then(r => r.json())
)
concurrentLimit(tasks, 3).then(results => {
console.log('全部完成:', results)
})
进阶版:支持回调通知
class ConcurrentPool {
constructor(limit) {
this.limit = limit
this.queue = []
this.active = 0
}
add(task) {
return new Promise((resolve, reject) => {
this.queue.push({ task, resolve, reject })
this.run()
})
}
run() {
while (this.active < this.limit && this.queue.length) {
const { task, resolve, reject } = this.queue.shift()
this.active++
task()
.then(resolve)
.catch(reject)
.finally(() => {
this.active--
this.run()
})
}
}
}
const pool = new ConcurrentPool(3)
urls.forEach(url => pool.add(() => fetch(url)))
实际应用场景
- 批量上传文件
- 爬虫控制并发
- 大量 API 请求需要限流
同分类其他题目