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







你可能感兴趣的:(javascript)