前言
关于如何实现LazyMan的试题,题目如下
实现一个LazyMan,可以按照以下方式调用: LazyMan(“Hank”)输出: Hi! This is Hank!
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出 Hi! This is Hank! //等待10秒.. Wake up after 10 Eat 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 5 Hi This is Hank! Eat supper 以此类推。
其实看到提意就知道要用到队列、Promise 等异步操作。然后我查阅了网上的资料好像关于这个 LazyMan 的实现方式倒不少,就说明这道题其实蛮有意思的,但大多都是关于 Promise 的实现,并没有 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 里则是把订阅的方法放到的最后一个栈执行