Promise限流

2,904 阅读1分钟

Promise限制并发请求,假设为了避免 IO 过大,需要限定10个并发数量

定义一个TaskLimit 方法

  • taskList 任务队列
  • count 当前进程中的任务数
  • limit 限制同事请求个数
function TaskLimit (limit) {
    this.taskList = []
    this.count = 0
    this.limit = limit
}

scanning,执行队列扫描

  • 这里伪造100个异步请求,响应时间随机
  • 判断最大数量,超出加入任务队列
const list = Array.from({ length: 100 }).map((item, index) => () => new Promise((resolve) => {
    console.log('list '+ index +' go')
    setTimeout(() => {
        resolve('list '+ index +' done')
    }, (index + 1) * 1000)
}))
TaskLimit.prototype.scanning = function (fn) {
    const { count, limit } = this
    if (count < limit) {
        return this.run(fn)
    } else {
        return this.hold(fn)
    }
}

run,前limit个任务立即执行

  • 在执行前count自增
  • 执行成功后唤醒队列
TaskLimit.prototype.run = function (fn) {
    this.count++
    return fn().then(data => {
        this.count--
        this.wakeUp()
        return data
    })
}

hold,超出limit的任务执行

  • count超过limit限制大小,排队执行
TaskLimit.prototype.hold = function (fn) {
    return new Promise((resolve, reject) => {
        this.taskList.push({fn, resolve, reject})
    })
}

wakeUp,上一个任务完成检测剩余任务数量,进行任务唤醒

  • 队列中还有等待的任务,执行
TaskLimit.prototype.wakeUp = function () {
    const { count, limit, taskList } = this
    if (count < limit && taskList.length) {
        const { fn, resolve, reject } = taskList.shift()
        this.run(fn).then(resolve).catch(reject)
    }
}

Promise.map

  • list 任务队列
  • limit 限制请求数量
Promise.map = function (list, limit) {
    const taskLimit = new TaskLimit(limit)
    Promise.all(list.map(item => taskLimit.scanning(item))).then((data) => {
        console.log(data)
    })
}
Promise.map(list, limit)

如何实现 Promise 的限流: Promise.map 的简单实现

异步循环打印

大佬,欢迎star,万分感谢