题目:
JavaScript 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个。完善代码中 Scheduler类,使得以下程序能正确输出。
需要注意的点:
-
add 函数后面有个.then 所以add函数是一个Promise对象
实现步骤:
-
因为add函数后面有个 .then ,所以在add函数里面我们需要return Promise
-
我们需要创建两个list,tasks 和 usingTask,usingTask是正在执行的任务队列,最多两个。taks是等待执行的任务队列
-
我们在add函数内return Promise之后,我们需要给当前函数 promiseCreator添加 resolve,用于在执行完之后,就是在then函数内跳出Promise
-
前面的步骤是先判断 usingTask 的长度是否小于2,小于2就添加到usingTask任务队列里,并直接执行。如果大于2,就先添加到tasks任务队列里,等待添加
-
我们在添加到usingTask 里之后,可以直接执行,执行好之后,也就是在then方法里,我们需要做三个事情
-
我们先使用 promiseCreator.resolve() 因为我们return 的是Promise对象,所以需要resolve
-
既然执行完了,就不需要在占usingTask 的位置,将其删除
-
最后将 tasks内的任务添加到 usingTask 内,并执行。因为是队列,所以我们需要调用 shift方法
实现代码:
class Scheduler {
constructor() {
this.tasks = [], // 待运行的任务
this.usingTask = [] // 正在运行的任务
}
// promiseCreator 是一个异步函数,return Promise
add(promiseCreator) {
return new Promise((resolve, reject) => {
promiseCreator.resolve = resolve
if (this.usingTask.length < 2) {
this.usingRun(promiseCreator)
} else {
this.tasks.push(promiseCreator)
}
})
}
usingRun(promiseCreator) {
this.usingTask.push(promiseCreator)
promiseCreator().then(() => {
promiseCreator.resolve()
let index = this.usingTask.findIndex(promiseCreator)
this.usingTask.splice(index, 1)
if (this.tasks.length > 0) {
this.usingRun(this.tasks.shift())
}
})
}
}
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(400, 4)
addTask(200, 2)
addTask(300, 3)
addTask(100, 1)
// 2, 4, 3, 1