小知识,大挑战!本文正在参与「程序员必备小知识」创作活动
本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。
导言
刷视频时发现的一道题,发现听有意思的,主要是考对数据结构中队列的了解。
LazyMan
1. 要求效果:
- 当输入:
LazyMan('张三').eat('lunch')
- 需要输出:
你好,我叫张三
吃午餐
- 当输入
LazyMan('张三').sleep('5').eat('dinner')
- 需要输出:
你好,我叫张三
(等待5秒)
我醒了,我刚睡了5秒
吃晚餐
- 当输入
LazyMan('张三').sleepFirst('5').eat('lunch').sleep('5').eat('dinner')
- 需要输出:
(等待5秒)
我醒了,我刚睡了5秒
你好,我叫张三
吃午餐
(等待5秒)
我醒了,我刚睡了5秒
吃晚餐
2. 解题思路
咋的一看,第一二效果感觉挺容易,但主要是第三个,就很难了,需要将 sleepFirst() 这个方法提前执行。看到这里其实就很容易想到 js 中的异步队列是不是,原理上其实都一样,利用数据结构中的队列实现。
那么解题思路就很清晰了:在函数体内维护一个队列,将所有方法通过 unshift 和 push 将插入到队列中, 随后使用一个 next() 方法, 不断将队列中的第一个方法取出调用。同时在每个方法的最后都返回一个 api 对象,来实现连式编程。总而言之就是在遇见方法时就将其插入到队列的最后,遇见需要先执行的方法,就将其插入到队列的最前方。
3. 具体代码
const LazyMan = name => {
// 维护一个队列
var queue = []
// 输出名字方法
const names = () => {
console.log(`你好,我叫${name}`)
next()
}
// 将输出名字方法插入这个队列
queue.push(names)
// 添加 next() 方法,负责将队列中第一个方法取出并执行
const next = () => {
// 如果队列中没有方法了就停止执行
if(queue.length <= 0) return false
// 使用数组中的 shift 方法将队列中的第一位取出
const first = queue.shift()
// 执行第一个方法
first()
}
// 声明一个 api 对象,当做自身方法扩展,实现链式编程
var api = {
// 程序运行到这里需要暂停指定时间
sleep(delay){
// 将这个方法 push 进队列
const sleeps = () => {
setTimeout(() => {
console.log(`我醒了,我刚睡了${delay}秒`)
next()
}, delay * 1000)
}
queue.push(sleeps)
// 返回对象
return api
},
// 表示代码在执行前需要暂停多久
sleepFirst(delay){
// 使用 unshift 将这个定时器插入队列的首位
const sleepFirsts = () => {
setTimeout(() => {
console.log(`我醒了,我刚睡了${delay}秒`)
next()
}, delay * 1000)
}
queue.unshift(sleepFirsts)
return api
},
// 吃晚餐还是吃午餐
eat(lunch){
const eats = () => {
// 使用三元表达式完成
console.log(lunch == 'lunch' ? '吃午餐' : '吃晚餐')
next()
}
queue.push(eats)
// 每个方法最后都得返回这个 api 对象,
return api
}
}
// 调用 next() 开始执行方法
setTimeout(() => {
next()
}, 100)
// 将这个 api 对象返回出去形成链式编程
return api
}