看到一个大佬写的控制异步并发数的函数,核心思想就是在并发数大于限制的时候,暂时先把操作放入通过promise组装一下,然后放入数组,每次执行完异步回调后就将操作按先入先出的顺序取出,然后执行,保证最大并发数在限制范围内。
代码如下:
class LimitPromise {
constructor (limit) {
this._limit = limit // 最大限制数
this._count = 0 // 目前并发的数量
this._taskQueue = [] // 如果并发数等于最大限制,则把新加的异步操作用数组存起来
}
}
LimitPromise.prototype.call = function (asyncFn, ...args) {
return new Promise((resolve, reject) => {
const task = this.createTask(asyncFn, args, resolve, reject)
if (this._count >= this._limit) {
this._taskQueue.push(task)
} else {
task()
}
})
}
LimitPromise.prototype.createTask = function (asyncFn, args, resolve, reject) {
return () => {
asyncFn(...args)
.then(resolve)
.catch(reject)
.finally(() => {
this._count--
if (this._taskQueue.length) {
let task = this._taskQueue.shift()
task()
}
})
this._count++
}
}
let limitP = new LimitPromise(3)
用一个异步函数sleep验证一下
function sleep(sec) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('等待了' + sec + '秒')
resolve()
}, sec * 1000)
})
}
limitP.call(sleep, 1) // 1秒后打印
limitP.call(sleep, 2) // 2秒后打印
limitP.call(sleep, 3) // 3秒后打印
limitP.call(sleep, 4) // 5秒后打印 1 + 4
limitP.call(sleep, 5) // 7秒后打印 2 + 5
limitP.call(sleep, 6) // 9秒后打印 3 + 6
结果:可以按正常顺序打印