乐趣区

面试题 LazyMan 的Rxjs实现方式

前言
笔者昨天在做某公司的线上笔试题的时候遇到了最后一道关于如何实现 LazyMan 的试题,题目如下
实现一个 LazyMan,可以按照以下方式调用:LazyMan(“Hank”) 输出:Hi! This is Hank!LazyMan(“Hank”).sleep(10).eat(“dinner”) 输出 Hi! This is Hank!// 等待 10 秒..Wake up after 10Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”) 输出 Hi This is Hank!Eat dinner~Eat supper~
LazyMan(“Hank”).sleepFirst(5).eat(“supper”) 输出 // 等待 5 秒 Wake up after 5Hi This is Hank!Eat supper 以此类推。

鉴于时间的原因只可惜本人当时并没写出来,我当时脑海里其实看到提意就知道要用到队列、Promise 等异步操作。然后我查阅了网上的资料好像关于这个 LazyMan 的实现方式倒不少,就说明这道题其实蛮有意思的,但大多都是关于 Promise 或 setTimeout 的实现,并没有 Rxjs 的实现方式,所以我就用一些操作符实现了这个 LazyMan
class LazyManModel {
queue: {timeout: number, fn: Function}[] = []
constructor() {
setTimeout(() => {
from(this.queue).pipe(
map(e => {
if (e.timeout) return of(e).pipe(delay(e.timeout * 1000));
return of(e)
}),
concatAll()
).subscribe(value => {
value.fn()
})
})
}

sleep(time: number): this {
this.queue.push({
timeout: time,
fn: () => { console.log(`Wake up after ${time}`) }
})
return this
}

eat(foot: string): this {
this.queue.push({
timeout: null,
fn: () => { console.log(`Eat ${foot}~`) }
})
return this
}

sleepFirst(time: number): this {
this.queue.unshift({
timeout: time,
fn: () => { console.log(`Wake up after ${time}`) }
})
return this
}

exported(): (name: string) => this {
return (name): this => {
this.queue.push({
timeout: null,
fn: () => { console.log(`Hi! This is ${name}!`) }
})
return this
}
}
}
示例
const LazyMan = new LazyManModel().exported();
LazyMan(‘Hank’).eat(‘foot’).eat(‘ping’).sleep(10).eat(‘pizza’).sleepFirst(5)
关于 setTimeout
我在 constructor 构造函数里使用了 setTimeout 是因为,在调用的时候是链式的,其作用域一直都在同一堆栈,而 setTimeout 里则是把订阅的方法放到的最后一个栈执行

退出移动版