/*
题设:JS 实现一个带并发限制的异步调度器 Scheduler,保证同时运行的任务最多有两个
举例如下:
addTask(1000,"1");
addTask(500,"2");
addTask(300,"3");
addTask(400,"4");
的输出顺序是:2 3 1 4
整个的完整执行流程:
一开始1、2两个任务开始执行
500ms时,2任务执行完毕,输出2,任务3开始执行
800ms时,3任务执行完毕,输出3,任务4开始执行
1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行
1200ms时,4任务执行完毕,输出4
*/
// 休眠函数
var asleep = time => new Promise((resolve) => {
setTimeout(resolve, time)
})
class Scheduler {
constructor(limit) {
this.maxLimit = limit // 最多同时运行数量
this.runCount = 0 // 当前正在运行任务个数
this.queue = [] // 运行任务队列
}
// 添加任务方法
add(promiseCreator) {
this.queue.push(promiseCreator)
}
// 启动任务入口函数
taskStart() {
for(let i = 0; i < this.maxLimit; i++) {
this.request()
}
}
// 真正调用异步调度方法,自身调用自身,循环执行,直到符合终止条件
request() {
// 终止条件
if(!this.queue || !this.queue.length || this.runCount >= this.maxLimit) {
return
}
// 增加当前运行任务个数
this.runCount++
// console.log('runCount: ', this.runCount)
// 队列头部任务运行
const promiseTask = this.queue.shift()
promiseTask().then(() => {
// 减少当前运行任务个数
this.runCount--
this.request()
})
}
}
// 调用
var scheduler = new Scheduler(2)
var addTask = (time, order) => {
scheduler.add(
() => asleep(time).then(() => {
console.log('order: ', order)
})
)
}
addTask(1000,"1")
addTask(500,"2")
addTask(300,"3")
addTask(400,"4")
// 启动任务
scheduler.taskStart()
思路:
1:有个空队列数组 queue;
2:将所有待执行请求任务塞进 queue 队列中;
3:调用入口函数 taskStart,并由函数中的 for 循环控制开始时的并发数量;
4:调用请求函数 request,当有个 request 函数异步完成时,通过监听,在 then 方法中再次调用
request 方法,从 queue 队列中,取出队头请求任务执行。
参考:JavaScript 中如何实现并发控制?、Promise的并发控制