xxleyi / learning_list

聚集自己的学习笔记
10 stars 3 forks source link

JS 异步队列手动实现 #223

Open xxleyi opened 4 years ago

xxleyi commented 4 years ago

可能是头条前端面试题

function Scheduler(size = 2) {
  this.maxSize = size
  this.taskCount = 0
  this.waiting = []
}

Scheduler.prototype.add = function (task) {
  return new Promise(resolve => {
    if (this.taskCount < this.maxSize) {
      this._execute(task, resolve)
    } else {
      this.waiting.push([task, resolve])
    }
  })
}

Scheduler.prototype._execute = function (task, resolve) {
  this.taskCount++
  task().then(() => {
    this.taskCount--
    resolve()
    if (this.waiting.length) {
      this._execute(...this.waiting[0])
      this.waiting = this.waiting.slice(1)
    }
  })
}

const timeout = (time) => new Promise(resolve => {
  setTimeout(resolve, time)
})

const scheduler = new Scheduler()
const addTask = (time, order) => {
  scheduler.add(() => timeout(time))
    .then(() => console.log(order))
}

addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// output: 2 3 1 4

// 调度逻辑要求:
// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4

// 实现思路:
// tasks 未满时,直接异步执行
// tasks 已满时,入 waiting 队列
// tasks 异步队列中每次执行后,wating 出队
// 重点实现 execute 函数