题目
class Scheduler {
add(promiseCreator) { ... }
// ...
}
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(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')// output: 2 3 1 4
// 一开始,1、2两个任务进入队列
// 500ms时,2完成,输出2,任务3进队
// 800ms时,3完成,输出3,任务4进队
// 1000ms时,1完成,输出1
// 1200ms时,4完成,输出4
先看add 这个函数,说明这个函数返回的是个promise,先写一个基本的返回promise的return
add() {
return new Promise((resolve, reject) => {
})
}
看这个addTask这个函数的返回,说明这就是经典promise题 最多并发数为x的问题,这道题的并发数为2。
看这个函数的输出结果是通过then链console出来的,输出值和add函数没有关系,add函数只需要里面的时间函数的status变为fulfilled时将自己的status也变成fulfilled即可
并发数的解题思路就是
1.建立一个任务队列,每次调用方法就将任务push进队列
2.建立一个执行队列,每次调用方法时都会查询这个队列中正在执行的任务是不是大于max个。如果大于max个,就将任务push进队列,并执行
3.每当任务执行完就从任务队列中推出一个任务,并把他push进执行队列并执行
const taskList = []
const runList = []
add(task){
taskList.push(task)
if(runList.length<2) {
const runTask = taskList.shift()
runList.push(runTask)
runTask().then(res => {
runList.remove(runTask) // 先写伪代码,具体实现可以后写
// 代补充 -- 处理resolve相关的逻辑去修改 promise的状态
if(taskList.length) {
const newTask = taskList.shift()
runList.push(newTask)
newTask.then(...)
}
})
}
}
发现出现了重复的逻辑,考虑可以把这块相同的代码这个抽成一个函数递归调用
const taskList = []
const runList = []
add(task) {
taskList.push(task)
if(runList.length<2) {
function f1() {
if(taskList.length) {
const runTask = taskList.shift()
runList.push(runTask)
runTask().then(res => {
runList.remove(runTask)
// 代补充 resolve 的逻辑
f1()
})
}
}
f1()
}
}
将这段逻辑放到之前写的return new Promise中,并试着resolve的逻辑
const taskList = []
const runList = []
add(task) {
return new Promise((resolve, reject) => {
taskList.push(task)
if(runList.length<2) {
function f1() {
if(taskList.length) {
const runTask = taskList.shift()
runList.push(runTask)
runTask().then(res => {
runList.remove(runTask)
resolve()
f1()
})
}
}
f1()
}
})
}
发现这么写resolve不对,递归的时候会出现问题,每次递归的resolve都用的是一个resolve。想想每个task都应该它的resolve绑定。那就要更改一下将任务推到任务队列时的逻辑
add(task) {
return new Promise((resolve, reject) => {
const newTask = {
task,
cb: (value) => {resolve(value)} // 因为这道题实现只需要改状态不需要传值。所以这里的value可传可不传
}
taskList.push(newTask)
...
runTask.task().then(res => {
runTask.cb(res)
})
})
}
整合一下, 并实现一下remove
class Scheduler{
// 转换成类里面的私有属性
taskList = []
runList = []
add(task) {
return new Promise((resolve, reject) => {
const newTask = {
task,
cb: (value) => {resolve(value)}
}
this.taskList.push(newTask)
if(this.runList.length<2) {
const f1 = () => { // 转换成类后这里要写成箭头函数,否则this指向会有问题
if(this.taskList.length) {
const runTask = this.taskList.shift()
this.runList.push(runTask)
runTask.task().then(res => {
// 实现remove逻辑
let index = this.runList.findIndex(val => val === runTask)
this.runList.splice(index, 1)
runTask.cb(res)
f1()
})
}
}
f1()
}
})
}
}
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(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')