实现 LazyMan 任务队列
使用任务队列实现链式调用和延迟执行
问题
实现一个 LazyMan,支持以下调用方式:
LazyMan('Jack')
.sleep(1)
.eat('lunch')
.sleepFirst(2)
.eat('dinner')
// 输出:
// (等待 2 秒)
// Wake up after 2 seconds
// Hi, I'm Jack
// (等待 1 秒)
// Wake up after 1 seconds
// Eat lunch
// Eat dinner
要求:
sleep(seconds)- 延迟执行后续任务sleepFirst(seconds)- 延迟执行,但优先级最高eat(food)- 输出吃什么- 支持链式调用
解答
class LazyManClass {
constructor(name) {
this.queue = []
// 初始任务:打招呼
this.queue.push(() => {
console.log(`Hi, I'm ${name}`)
this.next()
})
// 异步启动队列,确保链式调用的任务都已入队
setTimeout(() => {
this.next()
}, 0)
}
// 执行下一个任务
next() {
const task = this.queue.shift()
task && task()
}
sleep(seconds) {
this.queue.push(() => {
setTimeout(() => {
console.log(`Wake up after ${seconds} seconds`)
this.next()
}, seconds * 1000)
})
return this // 链式调用
}
sleepFirst(seconds) {
// 插入队列头部,优先执行
this.queue.unshift(() => {
setTimeout(() => {
console.log(`Wake up after ${seconds} seconds`)
this.next()
}, seconds * 1000)
})
return this
}
eat(food) {
this.queue.push(() => {
console.log(`Eat ${food}`)
this.next()
})
return this
}
}
function LazyMan(name) {
return new LazyManClass(name)
}
测试
LazyMan('Jack')
.sleep(1)
.eat('lunch')
.sleepFirst(2)
.eat('dinner')
执行流程分析
// 1. 构造函数执行,queue = [sayHi]
// 2. .sleep(1) 执行,queue = [sayHi, sleep1]
// 3. .eat('lunch') 执行,queue = [sayHi, sleep1, eatLunch]
// 4. .sleepFirst(2) 执行,queue = [sleep2, sayHi, sleep1, eatLunch]
// 5. .eat('dinner') 执行,queue = [sleep2, sayHi, sleep1, eatLunch, eatDinner]
// 6. setTimeout 回调执行,开始消费队列
关键点
- 任务队列:用数组存储所有待执行的任务函数
- 异步启动:
setTimeout(0)确保所有链式调用完成后再执行队列 - next 机制:每个任务执行完必须调用
next()触发下一个任务 - sleepFirst 实现:使用
unshift将任务插入队列头部 - 链式调用:每个方法返回
this
目录