题目
实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有N个。
完善下面代码中的 Scheduler 类,使得以下程序能正确输出:
class Scheduler {
add(promiseCreator) { ... }
// ...
}
const timeout = (time) => new Promise(resolve => {
setTimeout(resolve, time)
})
const scheduler = new Scheduler(n)
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => console.log(order))
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
// 打印顺序是:2 3 1 4
核心思路:考察 Promise
知识点;当任务数超过规定任务数,创建微任务
进行等待。
完善代码如下:
class Scheduler {
constructor(max) {
this.max = max;
this.count = 0; // 当前执行中的异步操作
this.queue = new Array(); // 记录当前的执行数组
}
async add(promiseCreator) {
// count >= max 时,此时先不直接执行,将当前异步操作存储起来,当count满足时,再去执行
// Promise.then的链式调用 new Promise((resolve) => { setTimeout(() => {}, 10000}).then xxxx
if (this.count >= this.max) {
/** 这个new Promise单纯只是为了创建个微任务去等,前面加了await,没有resolve()是不会往下走的 */
await new Promise((resolve, reject) => {
this.queue.push(resolve);
});
}
/** queue某一项resolve()后会从这儿往下走 */
this.count++;
let res = await promiseCreator();// 执行timeout(time)
this.count--; // 执行完1轮才往下走到这儿
if (this.queue.length) {
this.queue.shift()();//删除queue数组第一项并执行resolve()
}
return res;
}
}
const timeout = (time) => new Promise(resolve => {
setTimeout(resolve, time)
})
const scheduler = new Scheduler(n) // 任务2个=>n即为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')
运行结果如下:
其他
打印测试:
class Scheduler {
constructor(max) {
this.max = max
this.count = 0 // 当前执行中的异步操作
this.queue = new Array() // 记录当前的执行数组
}
async add(promiseCreator) {
// count >= max 时,此时先不直接执行,将当前异步操作存储起来,当count满足时,再去执行
// Promise.then的链式调用 new Promise((resolve) => { setTimeout(() => {}, 10000}).then xxxx
if (this.count >= this.max) {
await new Promise((resolve, reject) => {
this.queue.push(resolve)
})
}
this.count++
const res = await promiseCreator()
this.count--
if (this.queue.length) {
this.queue.shift()()
}
console.log('res: ', res)
return res
}
}
const timeout = (time) => new Promise(resolve => {
console.log('100')
setTimeout(resolve, time)
})
const scheduler = new Scheduler(2)
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => {console.log(order); return 'timeout'})
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
打印结果:
100
100
res: undefined
100
2
res: undefined
100
3
res: undefined
1
res: undefined
4
// 解释:
// ∵setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
// ∵this.queue.shift()()即resolve()是同步代码,∴先打印下一个’100’再return res打印’2’