题目分析
1. 函数链调用,那么每个函数必然返回 this对象指向本身才能继续无限调用
2. 函数链调用上只要有sleepFirst函数 ,这个函数必须自动提前执行,就 可以否定 函数通过 直接执行 的方式实现,那么就只能想到 事件队列方式 实现
原型对象方式实现
function LazyMan(name){
return new LazyManClass(name)
}
function mySleep(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms*1000)
})
}
function LazyManClass(name){
this.name = name;
this.task = [];
console.log(`Hi I am Tony`)
return this
}
LazyManClass.prototype.mySleep = function(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms*1000)
})
}
LazyManClass.prototype.nextTickTask = function(){
if(this.hasTask){
return
}
this.hasTask = true
new Promise(e=>{e()}).finally(async e=>{
while(this.task.length>0){
let { value, task } = this.task.shift();
if(task === 'sleepFirst' || task === 'sleep'){
await this.mySleep(value)
console.log(`等待 ${value*1000}秒`)
}else if(task === 'eat'){
console.log(`I am eatting ${value}`)
}
}
this.hasTask = false
})
return this
}
LazyManClass.prototype.sleepFirst = function(ms){
this.task.unshift({task:'sleepFirst',value:ms})
this.nextTickTask()
return this
}
LazyManClass.prototype.sleep = function(ms){
this.task.push({task:'sleep',value:ms})
this.nextTickTask()
return this
}
LazyManClass.prototype.eat = function(str){
this.task.push({task:'eat',value:str})
this.nextTickTask()
return this
}
function LazyMan(name){
return new LazyManClass(name)
}
LazyMan('Tony').eat('lunch').sleep(3).sleepFirst(5).eat('lunch1')
class类实现
class LazyManClass{
constructor(name=''){
this.name = name
this.task = []
console.log(`I am eating ${name}`)
}
nextTickTask(){
if(this.hasTask){
return
}
this.hasTask = true
new Promise(e=>{e()}).finally(async e=>{
while(this.task.length>0){
let { value, task } = this.task.shift();
if(task === 'sleepFirst' || task === 'sleep'){
await this.mySleep(value)
console.log(`等待 ${value*1000}秒`)
}else if(task === 'eat'){
console.log(`I am eatting ${value}`)
}
}
this.hasTask = false
})
return this
}
mySleep(ms){
return new Promise((resolve,reject)=>{
setTimeout(resolve,ms*1000)
})
}
sleepFirst(ms){
this.task.unshift({task:'sleepFirst',value:ms})
this.nextTickTask()
return this
}
sleep(ms){
this.task.push({task:'sleep',value:ms})
this.nextTickTask()
return this
}
eat(str){
this.task.push({task:'eat',value:str})
this.nextTickTask()
return this
}
}
function LazyMan(name){
return new LazyManClass(name)
}
LazyMan('Tony').eat('lunch').sleep(3).sleepFirst(5).eat('lunch1')