關於lazyMan鏈式調用的實現,面試題

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')







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章