题目
实现一个带并发限制的异步调度器 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 xxxxif (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 = maxthis.count = 0 this.queue = new Array() }async add(promiseCreator) {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
100res: undefined
100
2res: undefined
100
3res: undefined
1res: undefined
4
输出结果分析
- Part 1:
(1)addTask1000、addTask500:
走两次到这儿
this.count++
const res = await promiseCreator(); 都输出’100’,先打印2个'100'
(2)addTask300、addTask400:
/** 这个new Promise单纯只是为了创建个微任务去等,前面加了await,没有resolve()是不会往下走的 */
await new Promise((resolve, reject) => {
this.queue.push(resolve);
}); - Part 2:
(3)500ms的timeout先执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
;
(4)∵this.queue.shift()()即resolve()是同步代码,
addTask300走到这儿
this.count++
const res = await promiseCreator();
∴先打印下一个'100'
再return res打印'2'
- Part 3:
(5)接下来同理,300ms的timeout先执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
;
(6)∵this.queue.shift()()即resolve()是同步代码,
addTask400走到这儿
this.count++
const res = await promiseCreator();
∴先打印下一个'100'
再return res打印'3'
- Part 4:
(7)1000ms的timeout先执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
;
(8)没有下一个’100’了,return res打印'1'
; - Part 5:
(9)400ms的timeout执行完,setTimeout(resolve, time) resolve后面木有具体值,∴res: undefined
;
(10)没有下一个’100’了,return res打印'4'
;