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