实现以下功能
代码语言:javascript复制LazyMan('Tony');
// Hi I am Tony
LazyMan('Tony').sleep(10).eat('lunch');
// Hi I am Tony
// 等待了10秒...
// I am eating lunch
LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
// Hi I am Tony
// I am eating lunch
// 等待了10秒...
// I am eating diner
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
功能难点是要以指定顺序执行代码,方法调用顺序又不与执行顺序不对等,所以核心目的是创建一个任务队列,这个任务队列,必须是同步执行的,将子任务插入队列前面或者后面,依次执行这些任务 vue批量异步更新也似类是似的思想
- 首先搭建架子, Hi I am是无顺序变化的,立即执行,所以它最简单
class Lazy{
constructor(name){
console.log('Hi I am Tony')
}
}
function LazyMan(name) {
return new Lazy(name);
}
2.创建一个微任务队列
代码语言:javascript复制class Lazy{
constructor(name){
// 这个数组是我们的任务队列,保存这一个个函数,可能是异步也可能是同步
this.cbs=[];
console.log('Hi I am Tony')
// 创建一个微任务,微任务里面遍历执行每个任务(微任务不会立即执行,会在script执行栈执行完再开始)
this.runcbs()
}
runcbs(){
Promise.resolve().then(async res=>{
while(this.cbs.length){
// 移出任务队列中第一个元素,并且执行
await this.cbs.shift()()
}
})
}
eat(meal){
this.cbs.push(()=>console.log(`I am eating ${meal}`));
// 链式调用
return this;
}
sleep(time){
// 队列中加入异步任务,会同步执行
this.cbs.push(()=>new Promise(res=>{
setTimeout(()=>{
console.log(`等待了${time}秒...`)
res();
},time*1000)
}))
return this;
}
sleepFirst(time){
this.cbs.unshift(()=>new Promise(res=>{
setTimeout(()=>{
console.log(`等待了${time}秒...`)
res();
},time*1000)
}))
return this;
}
}
function LazyMan(name) {
return new Lazy(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');