题目描述

请实现一个 AsyncScheduler 类,用于控制异步任务的并发执行数量,满足以下要求: 构造函数接收最大并发数 concurrency。 提供 add(task) 方法,接收返回 Promise 的异步任务函数,返回一个新的 Promise。 任何时候同时运行的异步任务数量不超过 concurrency。 任务按照添加顺序依次开始执行(非并行任务的顺序保证)。 当某个任务失败时,不影响其他任务的执行。 进阶要求:支持任务取消功能(选做)。

思路&js代码

1、递归

class AsyncScheduler {
  constructor(concurrency) {
    // 初始化代码
    this.concurrency = concurrency
    this.tasks = []
    this.runningCount = 0
  }
 
  add(task) {
    this.tasks.push(task)
    this.runTask()
  }
 
  runTask() {
    // 没有待执行的任务,直接返回
    if (this.tasks.length === 0) return
 
    // 超出并发数,直接返回
    if (this.runningCount === this.concurrency) return
 
    this.runningCount++
 
    const nextTask = this.tasks.shift() // 从任务列表中取出第一个
    const onEnd = () => {
      this.runningCount--
      this.runTask()
    }
 
    nextTask().then(onEnd).catch(onEnd)
  }
 
  // 可选:取消任务的方法
  cancel(task) {
    if (!task) this.tasks = []
    this.tasks = this.tasks.filter(item => item !== task)
  }
}
 
const scheduler = new AsyncScheduler(2) // 最大并发数2
const delay = (ms, val) => () =>
  new Promise(resolve =>
    setTimeout(() => {
      console.log(val)
      resolve(val)
    }, ms)
  )
 
const consoleA = delay(1000, "A")
const consoleB = delay(500, "B")
const consoleC = delay(300, "C")
const consoleD = delay(200, "D")
 
scheduler.add(consoleA)
scheduler.add(consoleB)
scheduler.add(consoleC)
scheduler.add(consoleD)
 
// scheduler.cancel(consoleC)
 
// 输出:B、C、A、D