lazyMan鏈式調用
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner')
// Hi i am Tony
// 等待了10秒
// I am eating lunc
請實現一個這樣的東西。
第一反應,這不是鏈式調用嗎,我們常用的jquery就是這樣的啊。
仔細一看,中間那個sleep好像不太好弄。
怎麼樣才能讓他10秒後才執行下面的東東嘞??
那就先寫出個大概樣子
const LazyMan = function(name){
console.log(`Hi i am ${name}`);
let _lazyMan = {
sleep: function(time){
return this
},
eat: function(food){
return this
},
}
return _lazyMan;
}
首先是一個函數,然後返回一個對象,裏面有sleep方法和eat方法,並且能夠返回對象自身
那我們怎麼讓他執行sleep的時候延遲,然後執行鏈式後面的函數呢?
第一反應
sleep執行之後,馬上就會執行eat,這樣的話,就讓sleep 函數內部setTimeout,然後執行打印時間,然後執行eat函數不就行了嗎,
如果只是滿足鏈條長度爲3,就是硬性的執行吃->睡->吃,確實也能實現,也就是 代理執行了唄
那樣式這樣呢?
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner').eat('dinner').eat('dinner').eat('dinner')
中間睡一次,後面就使勁吃呢?那我們就要思考怎麼實現後面的好多吃了
那就是事件放在一個數組裏面,然後循環執行,我們還要加一個flag,來區分是否在睡,一個數組來放我們的方法。
const LazyMan = function(name){
console.log(`Hi i am ${name}`);
let _lazyMan = {
isSleep: false,
waitFun: [],
sleep: function(time){
this.isSleep = true
setTimeout(()=>{
console.log('I am sleep ' + time)
this.waitFun[0]()
this.waitFun.shift()
this.isSleep = false
},time)
return this
},
eat: function(food){
if(this.isSleep){
this.waitFun.push(this.lunch)
} else{
console.log('I am eat ' + food)
}
}
};
return _lazyMan;
}
大概就是這樣了,難度升級,我們讓他中間隨意睡睡吃吃睡睡,無規律,怎麼實現?難點在於每一次睡就要等待,然後執行鏈式相應的方法。
既然這樣,我們就把每一次睡之後的方法分組,然後根據分組來實現,實現後清空執行過的組,然後下一次睡醒了之後,執行該組的方法,這樣分析完之後就顯得很簡單了。代碼如下
const LazyMan = function(name){
console.log(`Hi i am ${name}`);
let _lazyMan = {
isSleep: false,
waitFun: [],
index: 0,
sleep: function(time){
if(this.isSleep){
this.putCbInWaitFun('sleep', time)
this.index++;
} else{
this.isSleep = true
setTimeout(()=>{
let waitFun = [...this.waitFun]
this.isSleep = false
console.log('I am sleep ' + time)
if (waitFun[0]) {
waitFun[0].forEach(cb => cb())
this.waitFun.shift()
}
}, time * 1000)
}
return this
},
eat: function(food){
if(this.isSleep){
this.putCbInWaitFun('eat', food)
} else{
console.log('I am eating ' + food)
}
return this
},
putCbInWaitFun: function(cb, param){
if(!this.waitFun[this.index]){
this.waitFun[this.index] = []
}
this.waitFun[this.index].push(this[cb].bind(this, param))
}
}
return _lazyMan;
}
LazyMan('Tony').eat('lunch').sleep(3).eat('dinner').sleep(3).eat('dinner')