Skip to content

1224 今日总结

今日计划

每天工作前/前一天晚上 做好计划:重点工作、自我提升、其他

重点工作

  • 房源列表页
  • 昨天的 上传组件问题处理

自我提升

其他

今日总结

问题,原因,解决方式,优化,巧妙实现,新知识


手撕代码/算法

防抖节流等各种手写,http 和网络,浏览器原理,性能优化,Webpack

字节面试题:JS 实现一个带并发限制的异步调度器 Scheduler

js
class Scheduler {
  constructor() {}
  add() {}
}

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

const scheduler = new Scheduler() // 并发限制为 2

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

addTask(1000, 1)
addTask(500, 2)
addTask(300, 3)
addTask(400, 4)

scheduler.start()
// output: 2 3 1 4

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

答案:

js
class Scheduler {
  constructor(limitNum) {
    this.limitNum = limitNum
    this.queue = []
    this.runningNum = 0;
  }

  add(taskFn) {
    this.queue.push(taskFn);
  }

  start() {
    for (let i = 0;i < this.limitNum;i++) {
      this.excute()
    }
  }

  excute() {
    if (this.queue.length && this.runningNum < this.limitNum) {
      this.runningNum++
      const fn = this.queue.shift();
      fn().then(() => {
        this.runningNum--;
        this.excute();
      })
    }

  }

}


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

const scheduler = new Scheduler(2) // 并发限制为 2 

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

addTask(1000, 1)
addTask(500, 2)
addTask(300, 3)
addTask(400, 4)

scheduler.start()
// output: 2 3 1 4

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

分析:主要有几个地方需要注意

  • 控制器 预执行队列 start 和 真正的执行队列 excute 需要分开;
  • 已执行完的 fn,在 fn.then(() => { /.../}) 进行状态控制,如 this.runningNum 的变化
  • 边界控制:队列 queue 的长度,限制数量的最大值,运行的 fn;

相关参考资料:

好文推荐/面经相关/博客项目推荐

有感好文,面经,博客,项目等

其他/TODOS

Released under the MIT License.