第 56 题:要求设计 LazyMan 类,实现以下功能

发布于 2022-08-03 21:44:47 字数 1991 浏览 10 评论 56

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

Answer

class LazyManClass {
    constructor(name) {
        this.taskList = [];
        this.name = name;
        console.log(`Hi I am ${this.name}`);
        setTimeout(() => {
            this.next();
        }, 0);
    }
    eat (name) {
        var that = this;
        var fn = (function (n) {
            return function () {
                console.log(`I am eating ${n}`)
                that.next();
            }
        })(name);
        this.taskList.push(fn);
        return this;
    }
    sleepFirst (time) {
        var that = this;
        var fn = (function (t) {
            return function () {
                setTimeout(() => {
                    console.log(`等待了${t}秒...`)
                    that.next();
                }, t * 1000);  
            }
        })(time);
        this.taskList.unshift(fn);
        return this;
    }
    sleep (time) {
        var that = this
        var fn = (function (t) {
            return function () {
                setTimeout(() => {
                    console.log(`等待了${t}秒...`)
                    that.next();
                }, t * 1000); 
            }
        })(time);
        this.taskList.push(fn);
        return this;
    }
    next () {
        var fn = this.taskList.shift();
        fn && fn();
    }
}
function LazyMan(name) {
    return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(56

柠檬心 2022-05-04 13:56:41 56 楼
class LazyMan {
    constructor(name) {
        this.tasks = []
        const task = () => {
            console.log(name)
        }
        this.tasks.push(task)
        setTimeout(() => {
            this.exec()
        })
    }

    sleep(time) {
        const task = () => new Promise(resolve => {
            setTimeout(resolve, time)
        })
        this.tasks.push(task)
        return this
    }
    sleepFirst(time) {
        const task = () => new Promise(resolve => {
            setTimeout(resolve, time)
        })
        let originTask = this.tasks.shift()
        this.tasks.unshift(originTask,task)
        return this
    }
    eat(food) {
        const task = () => {
            console.log(food)
        }
        this.tasks.push(task)
        return this
    }

     async exec() {
        for (let task of this.tasks) {
            await task()
        }
    }
}
熟人话多 2022-05-04 13:56:41 55 楼
    function LazyManClass(name){
        this.name = name;
        console.log('Hi I am '+name);
        //存储行为列表
        this.taskList = [];

        //声明类行为执行函数
        this.doTask = function(){
            var fn = this.taskList.shift();
            if(fn){
                fn();
            }
        };
        
        //异步执行默认行为函数
        var _this = this;
        setTimeout(function(){
            _this.doTask();
        },0);
        
    }
        

    LazyManClass.prototype.eat = function(food){
        var _this = this;
        var fn = function(){
            console.log('I am eating '+food);
            _this.doTask();
        }

        //维护行为列表
        this.taskList.push(fn);
        return this;
    }

    LazyManClass.prototype.sleepFirst = function(time){
        var _this = this;
        var fn = function(){
            setTimeout(function(){
                console.log('等待了 '+time+'秒...');
                _this.doTask();
            },time*1000)
        }
        
        //维护行为列表
        this.taskList.unshift(fn);
        return this;
    }

    LazyManClass.prototype.sleep = function(time){
        var _this = this;
        var fn = function(){
            setTimeout(function(){
                console.log('等待了 '+time+'秒...');
                _this.doTask();
            },time*1000)
        }

        //维护行为列表
        this.taskList.push(fn);
        return this;
    }

    //函数调用返回实例化对象
    function LazyMan(name){
        return new LazyManClass(name);
    }
    LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
   //感谢各位前辈们的代码思路,自己用es5写了一遍
掩于岁月 2022-05-04 13:56:41 54 楼

有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=

吹梦到西洲 2022-05-04 13:56:41 53 楼

有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=

我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完

软甜啾 2022-05-04 13:56:41 52 楼

有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=

我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完

如果真是这样那就好理解了,谢谢解答!!

踏月而来 2022-05-04 13:56:41 51 楼
function LazyMan(name) {
    console.log(`I am ${name}`);
    var task = [];
    function execute() {
	var fn = task.shift();
        fn && fn();	
    }
   // delay execute
    setTimeout(function() {
        execute();
    }, 0);
    function _sleep(n = 0) {
        console.log(`${name} is sleeping ${n}`);
        setTimeout(function() {
            execute();
        }, n * 1000);
    }
    function _eat(food) {
        console.log(`${name} is eating ${food}`);
        execute();
    }
    var obj = {
	sleep: function() {
	    task.push(_sleep.bind(null, ...arguments));
	    return obj;
        },
	eat: function() {
	    task.push(_eat.bind(null, ...arguments));
	    return obj;
	},
        sleepFirst: function() {
	    task.unshift(_sleep.bind(null, ...arguments));
	    return obj;
	}
    };
    return obj;
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
临风闻羌笛 2022-05-04 13:56:41 50 楼

有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=

我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完

如果真是这样那就好理解了,谢谢解答!!

在constructor中, next()方法执行在 setTimeout 中,setTimeout 是一个task,当 js 运行到 setTimeout 的时候,会把他放到 task 任务队列中,等到所有的同步的任务执行完后,就会执行setTimeout 中的this.next()方法 , 这个问题的关键问题是 js 的事件队列问题
你可以参考这个链接详细了解 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7?from=groupmessage&isappinstalled=0

不醒的梦 2022-05-04 13:56:41 49 楼
冷情妓 2022-05-04 13:56:41 48 楼

有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=

我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完

如果真是这样那就好理解了,谢谢解答!!

在constructor中, next()方法执行在 setTimeout 中,setTimeout 是一个task,当 js 运行到 setTimeout 的时候,会把他放到 task 任务队列中,等到所有的同步的任务执行完后,就会执行setTimeout 中的this.next()方法 , 这个问题的关键问题是 js 的_事件队列问题_ 。
你可以参考这个链接详细了解 https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/7?from=groupmessage&isappinstalled=0

首先谢谢解答和分享!

打小就很酷 2022-05-04 13:56:41 47 楼
class LazyMan {
  constructor(name){
    this.name = name
    this.eventQueue = []
    console.log('Hi , I am %s.', name )
    setTimeout(()=>{
      this.drain()
    },0)
  }
  eat(meal){
    const fn = function _eat(next){
      console.log('I am eating %s.',meal)
      next && next()
    }
    this.eventQueue.push(fn)
    return this
  }
  sleep(second){
    const fn = function _sleep(next){
      console.log('I am waiting %d second.', second)
      setTimeout(()=>{
        next && next()
      },second*1000)
    }
    this.eventQueue.push(fn)
    return this
  }
  sleepFirst(second){
    const fn = function _sleepFirst(next){
      console.log('I am waiting %d second.', second)
      setTimeout(()=>{
        next && next()
      },second*1000)
    }
    this.eventQueue.splice(0,0,fn)
    return this
  }
  drain(){
    const fnComposed = this.eventQueue.reduceRight(function _reduceRight(pre,next){
      return function (){
        return next(pre)
      }
    },)
    fnComposed()
  }
}
const TonyStark =new LazyMan('Tony').eat('lunch').sleep(10).eat('dinner');
轻许诺言 2022-05-04 13:56:41 46 楼

用了async,不需callback, 下面是两种方法放一起了。
第一种方法注释掉了,调用任务eat或者sleep或者sleepFirst时,把任务的data存放队列里,在init的方法里异步调用async executeTasks, 任务存放是同步的,先于异步的方法executeTasks执行完,在executeTasks方法里依次让任务data出列,然后执行相应的任务。

第二种是,使用next方法,每个任务最后都会调用一次next方法,把每个任务都压入队列,next的一次调用也是异步的,晚于同步的任务入列执行,next方法里让当前的任务入列,并执行。

function LazyMan(name) {
    return new LazyManClass(name);
}

class LazyManClass {
    constructor(name) {
        this.taskList = [];
        // used for method executeTasks
        // this.taskDataList = [];
        this.init(name);
    }

    init(name) {
        this.printLog('name', name);
        setTimeout(() => {
            // the alternative solution
            //this.executeTasks();
            this.next();
        }, 0);
    }

    printLog(type, data) {
        const LOG_MAP = {
            'name': `Hi, I am ${data}`,
            'eat': `I am eating ${data}.`,
            'sleep': `Waited for ${data} seconds.`,
            'error': `Got something wrrong: ${data}.`
        };
        console.log(LOG_MAP[type]);
    }

    delayPromise(t) {
        return new Promise(resolve => {
            setTimeout(() => {
                resolve();
            }, t * 1000);
        });
    };

    createTaskData(type, data) {
        return { type, data };
    }

    createTask(type, data) {
        return async () => {
            if (type === 'sleep') {
                try {
                    await this.delayPromise(data);
                }
                catch(e) {
                    this.printLog('error', e);
                }
            }
            this.printLog(type, data);
            this.next();
        }
    }

    addTask(type, data, isFirst=false) {
        if (isFirst) {
            // used for method executeTasks
            // this.taskList.unshift(this.createTask(type, data));
            this.taskList.unshift(this.createTask(type, data));
        } else {
            // used for method executeTasks
            // this.taskList.unshift(this.createTask(type, data));
            this.taskList.push(this.createTask(type, data));
        }
    }

    eat(str) {
        this.addTask('eat', str);
        return this;
    }

    sleep(t) {
        this.addTask('sleep', t);
        return this;
    }

    sleepFirst(t) {
        this.addTask('sleep', t, true);
        return this;
    }

    next() {
        if (this.taskList.length > 0) {
            let task = this.taskList.shift();
            task && task();
        }
    }
    async executeTasks() {
        let taskDataList = this.taskDataList;
        while (taskDataList.length > 0) {
            let { type, data } = taskDataList.shift();
            if (type === 'sleep') {
                try {
                    await this.delayPromise(data);
                }
                catch(e) {
                    this.printLog('error', e);
                }
            }
            this.printLog(type, data);
        }
    }
}
初见你 2022-05-04 13:56:41 45 楼

有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗

陌伤浅笑 2022-05-04 13:56:41 44 楼

有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗

立即执行函数的作用是在内部函数还没有执行的时候就已经为内部函数绑定好了对应参数的值,如果不用立即函数的话也可以用bind方法

var name = '小明'
var fn = function (n){
 console.log(`I am eating ${n}`)
 this.next()
}.bind(null, name)

上面的代码实际上是让fn等于下面这个函数:
function (){
 console.log(`I am eating 小明`)
 this.next()
}

这样一来无论你在什么地方执行fn都不需要传参数了,直接fn()不用参数也能达到和普通fn的fn(name )效果一样了

谁的年少不轻狂 2022-05-04 13:56:41 43 楼

不用类的实现,js里基本用类实现的用对象也可以实现。

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

下面是实现

let man = {
  queue: []
}

function LazyMan(name) {
  console.log(`Hi I am ${name}`)
  setTimeout(() => {
    man.next()
  }, 0)
  return man
}

man.eat = food => {
  man.queue.push(() => {
    console.log(`I am eating ${food}`)
    man.next()
  })
  return man
}

man.sleep = timeout => {
  man.queue.push(() => {
    setTimeout(() => {
      console.log(`等待了${timeout}秒`)
      man.next()
    }, timeout * 1000)
  })
  return man
}

man.sleepFirst = timeout => {
  man.queue.unshift(() => {
    setTimeout(() => {
      console.log(`等待了${timeout}秒`)
      man.next()
    }, timeout * 1000)
  })
  return man
}

man.next = () => {
  if (man.queue.length > 0) {
    man.queue.shift()()
  }
}
一抹苦笑 2022-05-04 13:56:41 42 楼
const LazyMan = name => new class Cp {
            constructor(name) {
                this.name = name;
                this._queues = []
                console.log(` Hi I am ${name}`)
                Promise.resolve().then(() => {
                    this.next()
                })
                // return this
            }
            static _sleep = time => new Promise(resolve => setTimeout(resolve, time * 1000))
            eat(ft) {
                this._queues.push(() => {
                    console.log(`I am eating ${ft}`)
                    this.next()
                })
                return this
            }
            sleepFirst(time) {
                this._queues.unshift(async () => {
                    await Cp._sleep(time)
                    console.log(`等待了 ${time} 秒`)
                    this.next()
                })
                return this
            }
            sleep(time) {
                this._queues.push(async () => {
                    await Cp._sleep(time)
                    console.log(`等待了 ${time} 秒`)
                    this.next()
                })
                return this
            }
            next() {
                const fn = this._queues.shift();
                fn && fn()
            }
        }(name)
    
    LazyMan('Tom');

    LazyMan('Tom').sleep(10).eat('lunch')

    LazyMan('Tom').eat('lunch').sleep(3).eat('dinner')

    LazyMan('Tom').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
吾家有女初长成 2022-05-04 13:56:41 41 楼

sleep怎么能用setTimeout来实现呢,这样只会限制sleep使用次数,多次出现sleep,就会有bug吧。幸好例子是只给了一个sleep,只能说过于特殊了,还可能是故意为之吧。

活泼老夫 2022-05-04 13:56:41 40 楼

有大佬能解答下next()调用的时机吗,这个运行流程我有点看不懂=。=

我不是大佬,但我理解的next()应该是在LazyMan('Toney')的时候异步执行的,因为异步,所以它还没干活的时候,链式调用早结束了,taskList也把要干的活按照规则存好了,随后它开始干活,由于taskList中每个活函数执行完后又主动调用了一次next(),所以能一直把taskList中的活干完

终于翻到的解析

半山落雨半山空 2022-05-04 13:56:41 39 楼
function LazyMan(name) {
  if (!(this instanceof LazyMan)) {
    return new LazyMan(name);
  }
  console.log(`Hi I am ${name}`);
  this.name = name;
  this.queue = [];
  this.isGoing = false;
  setTimeout(() => this.run(), 0);
}

LazyMan.prototype.eat = function (food) {
  const fn = () => console.log(`I am eating ${food}`);
  this.queue.push(fn);
  return this;
};
LazyMan.prototype.run = async function () {
  if (this.isGoing) return;
  this.isGoing = true;
  while (this.queue.length) {
    const cb = this.queue.shift();
    await cb();
  }
  this.isGoing = false;
  return this;
};
LazyMan.prototype.sleep = function (time) {
  const fn = () => new Promise((r) => setTimeout(r, time * 1000));
  this.queue.push(fn);
  return this;
};
LazyMan.prototype.sleepFirst = function (time) {
  const fn = () => new Promise((r) => setTimeout(r, time * 1000));
  this.queue.unshift(fn);
  return this;
};
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
滴情不沾 2022-05-04 13:56:41 38 楼
// 队列
class LazySuperMan1 {
  constructor(name) {
    this.name = name
    this.queue = []
    this.init()
  }

  init() {
    console.log('Hi I am ' + this.name)
    setTimeout(() => {
      this.next()
    }, 0)
  }

  sleepFirst(time) {
    this.queue.unshift(() => {
      setTimeout(() => {
        console.log(`等待了${time}秒`)
        this.next()
      }, time * 1000)
    })
    return this
  }

  sleep(time) {
    this.queue.push(() => {
      setTimeout(() => {
        console.log(`等待了${time}秒`)
        this.next()
      }, time * 1000)
    })
    return this
  }

  eat(food) {
    this.queue.push(() => {
      console.log('I am eating ' + food)
      this.next()
    })
    return this
  }

  next() {
    const fn = this.queue.shift()
    fn && fn()
  }
}

function LazyMan1(name) {
  return new LazySuperMan1(name)
}

LazyMan1('Tony')
  .eat('lunch')
  .eat('dinner')
  .sleepFirst(5)
  .sleep(10)
  .eat('junk food')

// 链表
class ListNode {
  constructor(val) {
    this.val = val
    this.next = null
  }
}

class LazySuperMan2 {
  constructor(name) {
    this.name = name
    this.head = new ListNode(null)
    this.current = this.head
    this.init()
  }

  init() {
    console.log('Hi I am ' + this.name)
    setTimeout(() => {
      this.current = this.head
      this.next()
    }, 0)
  }

  sleepFirst(time) {
    const first = new ListNode(() => {
      setTimeout(() => {
        console.log(`等待了${time}秒`)
        this.next()
      }, time * 1000)
    })
    first.next = this.head.next
    this.head.next = first
    return this
  }

  sleep(time) {
    this.current.next = new ListNode(() => {
      setTimeout(() => {
        console.log(`等待了${time}秒`)
        this.next()
      }, time * 1000)
    })
    this.current = this.current.next
    return this
  }

  eat(food) {
    this.current.next = new ListNode(() => {
      console.log('I am eating ' + food)
      this.next()
    })
    this.current = this.current.next
    return this
  }

  next() {
    if (this.current.next) {
      this.current = this.current.next
      this.current.val()
    }
  }
}

function LazyMan2(name) {
  return new LazySuperMan2(name)
}

LazyMan2('Tony')
  .eat('lunch')
  .eat('dinner')
  .sleepFirst(5)
  .sleep(10)
  .eat('junk food')
◇不必了。 2022-05-04 13:56:41 37 楼

订阅发布、任务机制(异步串行)

const _sayHi = Symbol('_sayHi') // 私有
class LazyManClass {
  constructor(name) {
    this.name = name
    this[_sayHi](name)

    this.handlerQueue = []
    this.tasks = []
    setTimeout(() => this.runTasks())
  }

  [_sayHi](name) {
    console.log('Hi I am ' + name)
  }

  // 异步串行
  runTasks() {
    const len = this.tasks.length
    const next = (i) => {
      if(i==len) return
      this.tasks[i](() => next(i+1))
    }
    next(0)
  }

  clear() {
    this.handlerQueue = []
  }

  run() {
    this.handlerQueue.forEach((fn) => fn())
    this.clear()
  }

  sleep(time) {
    this.run()

    const task = (cb) => {
      console.log('等待了' +  time + '秒')
      setTimeout(() =>{
        this.run()
        cb()
      }, time*1000)
    }
    this.tasks.push(task)
    return this
  }

  eat(food) {
    this.handlerQueue.push(() => console.log('I am eating' + food))
    return this
  }

  sleepFirst(time) {
    const queue = [...this.handlerQueue]
    const task = (cb) => {
      console.log('等待了' +  time + '秒')
      setTimeout(() =>{
        queue.forEach((fn) => fn())
        cb()
      }, time*1000)
    }
    this.tasks.push(task)
    this.handlerQueue = []
    return this
  }
}
function LazyMan(name) {
  return new LazyManClass(name);
}
// LazyMan('Tony');
// LazyMan('Tony').sleep(3).eat('lunch');
// LazyMan('Tony').eat('lunch').sleep(3).eat('dinner')
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(2).sleep(3).eat('junk food');
筱武穆 2022-05-04 13:56:41 36 楼
    // constructor里直接输出name
    // 定义task储存一系列任务
    // next方法负责执行每个任务
    // sleep, sleepfirst, eat 方法里都返回一个匿名函数,push到task中,等待执行,并在回调中执行next()以触发下一个任务
    // 不同的是sleepfirst是插到task前面,第一个执行
    class _Lazyman {
      constructor(name) {
        this.task = [];
        let that = this;
        console.log(`hi i'm ${name}`);
        setTimeout(() => {
          this.next();
        }, 0);
      }
      next() {
        let fn = this.task.shift();
        fn && fn();
      }
      sleepFirst(delay) {
        let that = this;
        let fn = (function(delay) {
          return function() {
            console.log(`等待${delay}s`);
            setTimeout(() => {
              console.log('sleepfirst');
              that.next();
            }, delay * 1000);
          };
        })(delay);
        this.task.unshift(fn);
        return this;
      }
      sleep(delay) {
        let that = this;
        let fn = (function(delay) {
          return function() {
            console.log(`等待${delay}s`);
            setTimeout(() => {
              console.log('i am wakeup');
              that.next();
            }, delay * 1000);
          };
        })(delay);
        this.task.push(fn);

        return this;
      }
      eat(str) {
        let that = this;
        let fn = (function(str) {
          return function() {
            console.log('i am eatting ' + str);
            that.next();
          };
        })(str);
        this.task.push(fn);
        return this;
      }
    }
    // 最后包装下_lazyman  , 因为调用时没有new
    function Lazyman(name){
      return new _Lazyman(name)
    }
    Lazyman('Tony')
      .eat('lunch')
      .sleepFirst(3).sleep(3)
      .eat('dinner');
尝蛊 2022-05-04 13:56:41 35 楼
function delay(s) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve()
        }, s * 1000);
    })
}

function Man(name) {
    this.queue = [() => {
        console.log(`this is ${name}`);
    }]

    setTimeout(async () => {
        while (this.queue.length) {
            const cur = this.queue.shift()

            if (typeof cur === 'function') {
                cur()
            }
            else {
                await delay(cur)
            }
        }
    }, 0);
}

Man.prototype.eat = function (food) {
    this.queue.push(() => {
        console.log(`eat ${food}`);
    })

    return this
}

Man.prototype.sleep = function (s) {
    this.queue.push(s)

    return this
}

Man.prototype.sleepFirst = function (s) {
    this.queue.unshift(s)

    return this
};

function LazyMan(name) {
    return new Man(name)
}

// LazyMan("tom").eat("apple").eat("banana");
// LazyMan("tom").sleep(1).eat("apple");
// LazyMan("tom");
LazyMan("tom").eat("banana").sleepFirst(1);
青衫儰鉨ミ守葔 2022-05-04 13:56:41 34 楼
class LazyMans {
    constructor(name) {
        this.name = name
        this.task = []
        setTimeout(() =>{
            console.log('Hi I am '+this.name)
            this.task.forEach(item => item())
        })
    }
    sleep(time) {
        this.task.push(() =>{
            let t = Date.now()
            while(Date.now() - t < time*1000){}
            console.log('等待了'+time+'秒')
        })
        return this
    }
    eat(str) {
        this.task.push(() => {
            console.log('I am eating '+str)
        })
        return this
    }
    sleepFirst(time) {
        this.task.unshift(() => {
            let t = Date.now()
            while(Date.now() - t < time*1000){}
            console.log('等待了'+time+'秒')
        })
        return this
    }
}

function LazyMan(name) {
    return new LazyMans(name)
}
涫野音 2022-05-04 13:56:41 33 楼
/**
 * 考察点
 * 1. 实现函数的链式调用
 * 2. 宏任务 vs 微任务
 * 3. 数据结构的应用(基于数组模拟链表)
 */
class LazyManClass {
  constructor(name) {
    this.name = name;
    this.tasks = []; // 将所有链式调用的函数放入到一个队列中,通过调用 next 方法执行函数队列中下一个函数

    console.log(`Hi I am ${name}`);

    // 在类被实例化时,会开启一个宏任务。实例化及后续的同步链式函数调用均在同一个宏任务中
    // 通过 setTimeout 新增一个宏任务,保证首次执行函数执行队列中的函数是在链式调用结束后开始
    setTimeout(() => {
      this.next();
    }, 0);
    // 也可以使用 Promise 代替此处 setTimeout 实现
    // Promise.resolve().then(() => {
    //   this.next();
    // });
  }

  // 执行函数队列中下一个函数
  next() {
    const fn = this.tasks.shift();
    fn && fn();
  }

  eat(food) {
    this.tasks.push(() => {
      console.log(`I am eating ${food}`);
      this.next();
    });
    return this; // 每一个链式调用的函数需要返回 this,确保队列中后续函数可以执行
  }

  _sleep(time) {
    setTimeout(() => {
      console.log(`等待了${time}秒...`);
      this.next();
    }, time * 1000);
  }

  sleep(time) {
    this.tasks.push(() => {
      this._sleep(time);
    });
    return this;
  }

  sleepFirst(time) {
    // 通过 unshift 将函数添加到函数队列的开头
    this.tasks.unshift(() => {
      this._sleep(time);
    });
    return this;
  }
}

function LazyMan(name) {
  return new LazyManClass(name);
}
沫尐诺 2022-05-04 13:56:41 32 楼

1、回调嵌套实现

class LazyManClass {
  constructor(name) {
    this.name = name
    this.tasks = []

    console.log('Hi I am Tony')
    setTimeout(() => {
      this.next()
    }, 0)
  }

  eat(something) {
    this.tasks.push(() => {
      console.log(`I am eating ${something}`)
      this.next()
    })
    return this
  }

  sleep(duration) {
    this.tasks.push(() => this._doSleep(duration))
    return this
  }

  sleepFirst(duration) {
    this.tasks.unshift(() => this._doSleep(duration))
    return this
  }

  _doSleep(duration) {
    setTimeout(() => {
      console.log(`等待了${duration}秒`)
      this.next()
    }, duration * 1000)
  }

  next() {
    if (this.tasks.length) {
      const task = this.tasks.shift()
      task()
    }
  }
}
function LazyMan(name) {
  return new LazyManClass(name)
}

2、promise 迭代实现

class LazyManClass {
  constructor(name) {
    this.name = name
    this.tasks = []
    console.log('Hi I am Tony')
    setTimeout(() => {
      this._interate()
    }, 0)
  }

  eat(something) {
    this.tasks.push(() => {
      console.log(`I am eating ${something}`)
    })
    return this
  }

  sleep(duration) {
    this.tasks.push(() => this._doSleep(duration))
    return this
  }

  sleepFirst(duration) {
    this.tasks.unshift(() => this._doSleep(duration))
    return this
  }

  _doSleep(duration) {
    return new Promise((resolve) => {
      setTimeout(() => {
        console.log(`等待了${duration}秒`)
        resolve()
      }, duration * 1000)
    })
  }

  async _interate() {
    // 用 for of 也行
    for await (const task of this.tasks) {
      await task()
    }
  }
}

function LazyMan(name) {
  return new LazyManClass(name)
}

测试

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
灼疼热情 2022-05-04 13:56:41 31 楼

有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗

可以这样用,task 箭头函数不接受参数,直接用外部 eat 方法的参数

  eat(food) {
    const task = () => {
      console.log(`I am eating ${food}`)
      this.next()
    }
    this.taskList.push(task)
    return this
  }
寂寞清仓 2022-05-04 13:56:41 30 楼
class LazyManClass {
  constructor(name) {
    console.log(`Hi I am ${name}`)
    setTimeout(async () => {
      for (const fn of this.task) {
        console.log(await fn())
      }
    })
  }
  task = []
  timeOut(time, isFirst = false) {
    this.task[isFirst ? 'unshift' : "push"](
      async () => new Promise(r =>
        setTimeout(() => r(`等待了${time}秒...`), time)
      )
    )
    return this
  }
  sleep(time) {
    return this.timeOut(time)
  }
  sleepFirst(time) {
    return this.timeOut(time, true)
  }
  eat(food) {
    this.task.push(async () => Promise.resolve(`I am eating ${food}`))
    return this
  }
}
const LazyMan = (name) => new LazyManClass(name)
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
深爱成瘾 2022-05-04 13:56:41 29 楼

for await of+async iterable方式:

function LazyMan(name) {
  let ins = Object.create({
    sleep: function(time) {
      this.stack.push({ log: `等待了${time}秒`, time });
      return this
    },
    eat: function(food) {
      this.stack.push({ log: `I am eating ${food}` });
      return this
    },
    sleepFirst: function(time) {
      this.stack.splice(1, 0, { log: `等待了${time}秒`, time });
      return this
    }
  });
  ins.stack = [];
  ins.stack.push({ log: `Hi I am ${name}` });
  (async function(stack) {
    const stackGen = function*() {
      for (let i = 0; i < stack.length; i++) {
        yield new Promise((resolve, reject) => {
          let { log, time = 0 } = stack[i];
          setTimeout(() => {
            resolve(log);
          }, time * 1000);
        });
      }
    }
    for await (let log of stackGen()) {
      console.log(log);
    };
  })(ins.stack);
  return ins;
}

递归方式:

function LazyMan(name) {
  let ins = Object.create({
    sleep: function(time) {
      this.stack.push({ log: `等待了${time}秒`, time });
      return this
    },
    eat: function(food) {
      this.stack.push({ log: `I am eating ${food}` });
      return this
    },
    sleepFirst: function(time) {
      this.stack.splice(1, 0, { log: `等待了${time}秒`, time });
      return this
    }
  });
  ins.stack = [];
  ins.stack.push({ log: `Hi I am ${name}` });
  Promise.resolve().then(() => {
    (function recursionExec(stack) {
      let { log, time = 0 } = stack.shift();
      new Promise((resolve, reject) => {
        setTimeout(() => {
          resolve(log);
        }, time * 1000);
      }).then((log) => {
        console.log(log);
        if (stack.length != 0) {
          recursionExec(stack);
        }
      });
    })(ins.stack);
  });
  return ins;
}
魔法少女 2022-05-04 13:56:41 28 楼

有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗

有没有大佬解答一下,这里传立即执行函数的返回值(函数)和直接传红字部分的函数,有什么区别吗

应该是闭包 保存变量 吧

蓝天白云 2022-05-04 13:56:41 27 楼
function LazyMan(name) {
  return new (class LazyMan {
    constructor() {
      this.name = name;
      console.log(`Hi I am ${name}`);
      this.taskList = [];
      setTimeout(async () => {
        for (const cb of this.taskList) {
          await cb();
        }
      }, 0);
    }

    eat(period) {
      this.taskList.push(() => console.log(`I am eating ${period}`));
      return this;
    }

    sleep(sec, isFirst = false) {
      const method = isFirst ? "unshift" : "push";
      this.taskList[method](
        async () =>
          await new Promise((resolve) => {
            setTimeout(() => {
              console.log(`wait for ${sec} seconds`);
              resolve();
            }, sec * 1000);
          })
      );
      return this;
    }

    sleepFirst(sec) {
      return this.sleep(sec, true);
    }
  })();
}

LazyMan("Tony")
  .eat("lunch")
  .eat("dinner")
  .sleepFirst(5)
  .sleep(10)
  .eat("junk food");
欲拥i 2022-05-04 13:56:41 26 楼
function LazyMan(name) {
      console.log(`Hi I am ${name}`);
      const _obj = {
        callback: [],
        pushCallback(cb, unshift = false) {
          if (unshift) return this.callback.unshift(cb);
          this.callback.push(cb);
        },

        _init() {
          setTimeout(() => {
            let idx = 0, self = this;
            function _inner(idx) {
              new Promise(async (resolve, reject) => {
                const callback = self.callback[idx];
                await callback();
                resolve();
              }).then(() => {
                idx++;
                if (idx < self.callback.length) {
                  _inner(idx);
                }
              });
            }
            _inner(idx);
          }, 0);
        },

        eat(eatTime) {
          this.pushCallback(() => {
            console.log(`I am eating ${eatTime}`);
          },
          );
          return this;
        },
        sleep(delay) {
          this.pushCallback(() => {
            return new Promise((resolve, reject) => {
              console.log(`要等待${delay}秒...`);
              setTimeout(() => {
                resolve();
              }, delay * 1000)
            })
          },
          );
          return this;
        },
        sleepFirst(delay) {
          this.pushCallback(() => {
            return new Promise((resolve, reject) => {
              console.log(`要等待${delay}秒...`);
              setTimeout(() => {
                resolve();
              }, delay * 1000)
            })
          }, true);
          return this;
        }
      };
      _obj._init();
      return _obj;
    }
盛夏已如深秋| 2022-05-04 13:56:41 25 楼

类似于消息队列一样,排队取出任务执行,sleepFirst 就像是优先级更高的任务

function LazyManClass(name) {
  this.name = name
  this.queue = []
  console.log(`Hi I am ${name}`)
  Promise.resolve().then(() => {
    this.next()
  })
}

LazyManClass.prototype.eat = function (eatName) {
  this.queue.push(() => {
    console.log(`I am eating ${eatName}`)
    this.next()
  })
  return this
}

LazyManClass.prototype.sleepFirst = function (time) {
  this.queue.unshift(() => {
    setTimeout(() => {
      console.log(`等待了${time}秒...`)
      this.next()
    }, time * 1000)
  })
  return this
}

LazyManClass.prototype.sleep = function (time) {
  this.queue.push(() => {
    setTimeout(() => {
      console.log(`等待了${time}秒...`)
      this.next()
    }, time * 1000)
  })
  return this
}

LazyManClass.prototype.next = function () {
  var task = this.queue.shift()
  task && task()
}

function LazyMan(name) {
  return new LazyManClass(name)
}
仅此而已 2022-05-04 13:56:41 24 楼
   //函数式写法

   
   function LazyMan(name) {

        const createMan = (name) => {
            console.log(`Hi I am ${name}`);
            let queue = []

            let pending = true
            const run = () => {
                if (!pending) return
                pending = false
                Promise.resolve().then(() => {
                    queue.reduce((promise, fn) => {
                        return promise.then(fn)
                    }, Promise.resolve())
                })
            }

            const wrap = (action, instance,first) => {
                return (...args) => {
                    const fn = () => action(...args)
                    first ? queue.unshift(fn) : queue.push(fn)
                    run()
                    return instance
                }
            }
            const eat = (meal) => {
                console.log(`I am eating ${meal}`);
            }
            const sleep = (time) => {
                return new Promise(resolve=>{
                    setTimeout(()=>{
                        console.log(`等待了${time}秒...`);
                        resolve()
                    },time*1000)
                })
            }

            const instance = {
                eat: null,
                sleep: null,
            }
            instance.eat = wrap(eat, instance)
            instance.sleep = wrap(sleep, instance)
            instance.sleepFirst = wrap(sleep, instance, true)
            return instance
        }

        const instance = createMan(name)
        return instance
    }
追风人 2022-05-04 13:56:41 23 楼

构造函数中加入开始执行任务队列的语句会导致延迟添加的任务无法执行,例如:

const lazyMan = LazyMan('name');
setTimeout(() => {
    lazyMan.eat('lunch');
}, 200)

以下是我的解决方法,将setTimeout封装进“添加任务”的函数中以实现延迟执行

class LazyManClass {
    constructor (name) {
        this.name = name;
        console.log(`Hi I am ${name}`);

        this.taskQueue = [];
        this.activeTimer = 0;
    }

    static getHaveMealTask (meal) {
        return () => { console.log(`I am eating ${meal}`); }
    }

    static getSleepTask (seconds) {
        return () => {
            console.log(`等待${seconds}秒...`)
            return new Promise((resolve) => {
                setTimeout(() => {
                    resolve()
                }, seconds * 1000)
            })
        }
    }

    async activeTasks () {
        let task = null;
        while (task = this.taskQueue.pop()) {
            await task();
        }
    }

    enqueueTask (task, index = 0) {
        if (index === 0) {
            this.taskQueue.unshift(task);
        } else if (index === 'head') {
            this.taskQueue.push(task);
        } else {
            this.taskQueue.splice(index, 0, task);
        }
        
        clearTimeout(this.activeTimer);
        this.activeTimer = setTimeout(() => {
            this.activeTasks();
        });
    }

    eat (meal) {
        this.enqueueTask(LazyManClass.getHaveMealTask(meal));
        return this;
    }

    sleep (seconds) {
        this.enqueueTask(LazyManClass.getSleepTask(seconds));
        return this;
    }

    sleepFirst (seconds) {
        this.enqueueTask(LazyManClass.getSleepTask(seconds), 'head');
        return this;
    }
}

function LazyMan (name) {
    return new LazyManClass(name);
}

// Hi I am Tony
// 等待5秒...
// I am eating lunch
// I am eating dinner
// 等待10秒...
// I am eating junk food
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
孤单情人 2022-05-04 13:56:41 22 楼

用防抖来解:


const stop = (s = 0) => {
    return new Promise(resolve => {
        setTimeout(resolve, s * 1000 );
    })
}

class LazyMan {

    constructor(name) {
        console.log('Hi I am ' + name);
        this.queue = [];
        this.timer = null;
    }

    debounce() {
        if(this.timer) {
            clearTimeout(this.timer);
            this.timer = null;
        }
        this.timer = setTimeout(() => {
            this.handleQueue();
            this.timer = null;
        }, 10);
    }

    sleep(s) {
        this.debounce();
        this.queue.push(async () => {
            await stop(s);
            console.log(`等待了${s}秒...`);
        });
        return this;
    }

    sleepFirst(s) {
        this.debounce();
        this.queue.unshift(async () => {
            await stop(s);
            console.log(`等待了${s}秒...`);
        });
        return this;
    }

    eat(food) {
        this.debounce();
        this.queue.push(() => {
             console.log(`I am eating ${food}`);;
        });
        return this;
    }

    async handleQueue() {
        while(this.queue.length > 0) {
            const run = this.queue.shift();
            await run();
        }
    }

}

ら。栖息 2022-05-04 13:56:41 21 楼
function LazyMan(name) {
  console.log(`Hi I am ${name}`)
  let next = Promise.resolve()

  this.sleep = function(time) {
    Promise.resolve().then(() => {
      next = next.then(() => new Promise(resolve => setTimeout(resolve, time * 1000)))
    })
    return this
  }

  this.eat = function(name) {
    Promise.resolve().then(() => {
      next = next.then(() => new Promise(resolve => {
        console.log(`I am eating ${name}`)
        resolve()
      }))
    })
    return this
  }

  this.sleepFirst = function(time) {
    next = new Promise(resolve => setTimeout(resolve, time * 1000))
    return this
  }
  return this
}

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
猫卆 2022-05-04 13:56:41 20 楼
class LazyManClass {
  constructor(name) {
    this.name = name;
    this.queue = [];
    this.sayName();
    setTimeout(() => {
      this.doSth();
    }, 0);
  }
  sayName() {
    console.log(`Hi I am ${this.name}`);
  }
  eat(food) {
    this.queue.push({ action: "doEat", sth: food });
    return this;
  }
  doEat(food) {
    console.log(`I am eating ${food}`);
  }
  sleep(time) {
    this.queue.push({ action: "doSleep", sth: time });
    return this;
  }
  sleepFirst(time) {
    this.queue.unshift({ action: "doSleep", sth: time });
    return this;
  }
  doSleep(time) {
    setTimeout(() => {
      console.log(`${time} sencond later...`);
      this.doSth();
    }, time * 1000);
  }
  doSth() {
    while (this.queue.length) {
      const { action, sth } = this.queue.shift();
      this[action](sth);
      if (action === "doSleep") {
        break;
      }
    }
  }
}
const LazyMan = function (name) {
  return new LazyManClass(name);
};

export default LazyMan;
小镇女孩 2022-05-04 13:56:41 19 楼
function LazyMan(name) {
  this.name = name;
  this.task = [];

  console.log(`Hi I am ${this.name}`);

  setTimeout(async () => {
    while (this.task.length) await this.task.shift()();
  }, 4);

  this.eat = function (food) {
    this.task.push(console.log.bind(this, `I am eating ${food}`));
    return this;
  };

  this.sleepFirst = function (timeout) {
    this.task.splice(0, 0, async () => {
      return new Promise((resolve) => setTimeout(resolve, timeout * 1000));
    });
    return this;
  };

  this.sleep = function (timeout) {
    this.task.push(async () => {
      return new Promise((resolve) => setTimeout(resolve, timeout * 1000));
    });
    return this;
  };

  return this;
}
甜味拾荒者 2022-05-04 13:56:41 18 楼
class LazyManClass {
  constructor(name) {
    this.taskList = [];
    this.name = name;
    console.log(`Hi I am ${this.name}`);
    Promise.resolve().then(async() => {
      await this.next();
    });
  }
  eat(name) {
    this.taskList.push(() => new Promise((resolve) => {
      console.log(`eat${name}`);
      resolve();
    }));
    return this;
  }
  sleepFirst(time) {
    this.taskList.unshift(() => new Promise((resolve) => {
      setTimeout(() => {
        console.log(`等待了${time}秒...`);
        resolve();
      }, time * 1000);
    }));
    return this;
  }
  sleep(time) {
    this.taskList.push(() => new Promise((resolve) => {
      setTimeout(() => {
        console.log(`等待了${time}秒...`);
        resolve();
      }, time * 1000);
    }));
    return this;
  }
  async next() {
    while(this.taskList.length){
      await this.taskList.shift()();
    }
  }
}
function LazyMan(name) {
  return new LazyManClass(name);
}
LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(4).eat('junk food');
高冷爸爸 2022-05-04 13:56:41 17 楼

function lazyMan(name) {
class LazyMan {
constructor(name) {
this.name = name;
this._queues = [];
console.log(Hi I am ${name});
setTimeout(() => {
this.next();
}, 0);
}
sleep(t) {
const fn = (() => {
return async () => {
console.log(等待了${t}s);
this.next();
};
})(t);
this._queues.push(fn);
return this;
}
eat(food) {
const fn = (() => {
return async () => {
console.log(I am eating${food});
this.next();
};
})(food);
this._queues.push(fn);
return this;
}
sleepFirst(t) {
const fn = (() => {
return async () => {
console.log(等待了${t}s);
this.next();
};
})(t);
this._queues.unshift(fn);
return this;
}
next() {
const fn = this._queues.shift();
fn && fn();
}
}

return new LazyMan(name);

}

lazyMan("Tony")
.eat("lunch")
.eat("dinner")
.sleepFirst(5)
.sleep(10)
.eat("junk food");

伴我心暖 2022-05-04 13:56:41 16 楼
class LazyMan{
  constructor(name){
    this.name = name;
    this.tasks = [];
    //宏任务延时执行
    setTimeout(()=>{
      this.start();
    },0)
  }
  sleep(time){
    this.tasks.push(()=>{
      return new Promise((resolve)=>{
        setTimeout(()=>{
          console.log('等待了几秒')
            resolve()
        },time*1000)
      })
    })
    return this;
  }

  eat(param){
      this.tasks.push(()=>{
        console.log(`eat ${param}`);
      })
      return this;
  }
  sleepFirst(time){
     this.tasks.unshift(()=>{
      return new Promise((resolve)=>{
        setTimeout(()=>{
          console.log('first 等待了几秒')
            resolve()
        },time*1000)
      })
    })
    return this;
  }
  async start(){
    for(let task of this.tasks){
      await task();
    }
  }
}

(new LazyMan('Tony')).eat('lunch').eat('dinner').sleepFirst(1).sleep(3).eat('junk food');
一花一树开 2022-05-04 13:56:41 15 楼
function LazyMan(name) {
    return new Man(name)
}

class Man {
    constructor(name) {
        this.tasks = []
        console.log(`Hi I am ${name}`)
        this.run()
    }
    createTask(word, time = 0) {
        let task
        if (time) {
            task = () => {
                setTimeout(() => {
                    word && console.log(word)
                    this.next()
                }, time * 1000)
            }
        } else {
            task = () => {
                console.log(word)
                this.next()
            }
        }
        return task
    }
    eat(food) {
        this.tasks.push(this.createTask(`I am eating ${food}`))
        return this
    }
    sleepFirst(time) {
        this.tasks.unshift((this.createTask(undefined, time)))
        return this
    }
    sleep(time) {
        this.tasks.push(this.createTask(undefined, time))
        return this
    }
    next() {
        if (this.tasks.length) {
            this.tasks.shift()()
        }
    }
    run() {
        setTimeout(() => {
            this.next()
        }, 0)
    }
}
国产ˉ祖宗 2022-05-04 13:56:38 14 楼
class LazyManClass {
    constructor(props){
        this.sub = []
        console.log(`Hi I am ${props}`)
        setTimeout(()=>{
            this.start()
        },0)
    }
    eat (params){
        this.sub.push(function(){
            console.log(`I am eating ${params}`)
        })
        return this
    }
    sleepFirst(s){
        this.sub.unshift(this.delay(s))
        // 这边还没有返回  同步就继续执行了
       return this
    }
    delay(s) {
        return () => {
            return new Promise(resolve => {
                setTimeout(function () {
                    console.log(`等待了${s}秒...`)
                    resolve()
                },s * 1000)
            })
        }
    }
    sleep (s){
        this.sub.push(this.delay(s))
        // 这边还没有返回  同步就继续执行了
       return this
    }
    async start(){
        for (const iterator of this.sub) {
            await iterator()
        }
    }
}
function LazyMan(props) {
    return  new LazyManClass(props)
}
LazyMan('Tony').eat('lunch').eat('diner').sleepFirst(1).sleep(2).eat('junk food')
// Hi I am Tony
// 等待了5秒...
// I am eating lunch
// I am eating dinner
// 等待了10秒...
// I am eating junk food
站稳脚跟 2022-05-04 13:56:38 13 楼
function LazyMan(name) {
    if (!(this instanceof LazyMan)) {
        return new LazyMan(name);
    }
    this.name = name;
    this.delayTime = 0;
    this.tasks = [];
    console.log(`Hi I am ${this.name}`);
    this._ready();
}

LazyMan.prototype._ready = function () {
    setTimeout(() => {
        setTimeout(() => {
            console.log(`等待了${this.delayTime}秒...`);
            this._doTasks();
        }, this.delayTime * 1000);
    }, 0);
}

LazyMan.prototype._doTasks = function () {
    const tasks = this.tasks;
    if (tasks.length === 0) return;
    const {delayTime, callback} = tasks[0];
    setTimeout(() => {
        callback && callback();
        tasks.shift();
        this._doTasks();
    }, delayTime);
}

LazyMan.prototype.eat = function (foods) {
    this.tasks.push({
        delayTime: 0,
        callback() {
            console.log(`I am eating ${foods}`);
        },
    });
    return this;
}

LazyMan.prototype.sleep = function (seconds) {
    if (seconds >= 0) {
        this.tasks.push({
            delayTime: seconds * 1000,
            callback() {
                console.log(`等待了${seconds}秒...`)
            }
        });
    }
    return this;
}

LazyMan.prototype.sleepFirst = function (seconds) {
    if (seconds > 0) {
        this.delayTime = seconds;
    }
    return this;
}
梦与时光遇 2022-05-04 13:56:38 12 楼
function LazyMan(name) {
  if (this instanceof LazyMan) {
    this.task = [];
    this.log('Hi I am '+ name);
    setTimeout(() => {
      this.next();
    }, 0);
  }
  return (this instanceof LazyMan) && this || new LazyMan(name);
}

LazyMan.prototype.log = console.log;

LazyMan.prototype.next = function() {
  const [fn, ...tail] = this.task;
  fn && (this.task = tail) && fn();
}

LazyMan.prototype.eat = function(food) {
  this.task = [
    ...this.task,
    () => {
      this.log('I am eating '+ food);
      this.next();
    }
  ]
  return this;
}

LazyMan.prototype.sleep = function(timeout) {
  this.task = [
    ...this.task,
    () => {
      setTimeout(() => {
        this.next();
      }, timeout * 1000);
    }
  ]
  return this;
}

LazyMan.prototype.sleepFirst = function(timeout) {
  this.task = [
    () => {
      setTimeout(() => {
        this.next();
      }, timeout * 1000)
    },
    ...this.task
  ]
  return this;
}


LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(1).sleep(2).eat('junk food');
她比我温柔 2022-05-04 13:56:38 11 楼

// 写一个 setTimeout 就可以了。

class lazyManClass {
    constructor(name){
        this.taskList = []
        this.init(name)
    }

    init(name){
        var _this = this
        this.taskList.push({
            time: 0, // 是否是异步
            fn:(function(s){ // 函数自执行
                    return function() {
                        _this.exec()
                        console.log('Hi I am ', s)
                    }
                })(name)
        })
        this.exec()
        return this
    }
    eat(str) {
        var _this = this
        this.taskList.push({
            time: 0,
            fn: (function(s){
                    return function() {
                        _this.exec()
                        console.log('I am eating ', s)
                    }
                })(str)
        })
        
        return this
    }
    sleep(t){
        var _this = this
        this.taskList.push({
            time: t * 1000,
            fn: (function(time){
                    return function() {
                        _this.exec()
                        console.log(`等待了${time}秒...`) 
                    }
                })(t)
        })
        return this
    }
    sleepFirst(t) {
        var _this = this
        this.taskList.unshift({
            time: t * 1000,
            fn: (function(time){
                    return function() {
                        _this.exec()
                        console.log(`等待了${time}秒...`) 
                    }
                })(t)
        })
        return this
    }
    exec(){
        var obj = this.taskList.shift()
        if(!obj) {
            return   // 最后一个fn里面,也会执行 _this.exec(),这个时候taskList已经空了
        }
        setTimeout(() => {
            obj.fn && obj.fn.call(this)
        }, obj.time || 0)
        
    }
}

function LazyMan(name) {
    return new lazyManClass(name)
}   

七月上 2022-05-04 13:56:38 10 楼
class LazyMan {
	constructor (user) {
		this.timeList = [];
		console.log(`Hi I am ${user}`)
		Promise.resolve().then(res => this.next());
	}
	eat (res) {
		var fn =  () => {
			console.log(`I am eating ${res}`);
			this.next();
		}
		this.timeList.push(fn);
		return this;
	}
	sleep (time) {
		var fn = res => {
			setTimeout(res => {
				console.log(`等待了${time}秒`);
				this.next();
			},time*1000)
		}
		this.timeList.push(fn);
		return this;
	}
	next () {
		var fn = this.timeList.shift();
		fn && fn();
	}
	sleepFrist (time) {
		var fn = res => {
			setTimeout(res => {
				console.log(`先等待了${time}秒`);
				this.next();
			},time*1000)
		}
		this.timeList.unshift(fn);
		return this;
	}
}
function lazyman (res) {
	return new LazyMan(res)
}
_//lazyman('静静').sleep(2).eat('饺子').sleep(3).eat('面').sleepFrist(1).eat('others')
//Hi I am 静静
//先等待了1秒
//等待了2秒
//I am eating 饺子
//等待了3秒
//I am eating 面
//I am eating others_
沒落の蓅哖 2022-05-04 13:56:30 9 楼
/**
 * 普通 eat方法, 存放在立即执行队列中, 用settimeout来执行
 * sleep 方法  每次调用这个方法, 都单独开一个定时器, 把新的任务加入到这个队列
 * sleepFirst方法 把立即执行的任务队列的任务 塞到新的定时器任务队列
 */

class LazymanClass {
  constructor (_name = '') {
    this._immediateTask = []
    this._immediateTimer = null
    this._sleepTaskMap = {}
    this._curSleepTaskKey = null
    this._log(`Hi i am ${_name}`)
  }

  eat (meal) {
    // 添加新任务之前 清空之前的 立即定时器
    this._immediateTimer && clearTimeout(this._immediateTimer)

    const _eat = (meal) => {
      this._log(`i am eating ${meal}`)
    }

    if (this._curSleepTaskKey === null) {
      this._immediateTask.push(_eat.bind(this, meal))
    } else {
      this._sleepTaskMap[this._curSleepTaskKey].push(_eat.bind(this, meal))
    }

    this._immediateTimer = setTimeout(() => {
      this._runImmeadiateTask()
    })
    return this
  }

  sleep (second) {
    const key = Math.random()
    this._curSleepTaskKey = key
    this._sleepTaskMap[this._curSleepTaskKey] = []
    setTimeout(() => {
      this._log(`等待了${second}秒`);
      this._runSleepTask(key)
    }, second * 1000)
    return this
  }

  sleepFirst (second) {
    const key = Math.random()
    this._curSleepTaskKey = key
    this._sleepTaskMap[key] = []
    this._immediateTask.map(task => {
      this._sleepTaskMap[key].push(task)
    })
    this._immediateTask = []

    setTimeout(() => {
      this._log(`等待了${second}秒`);
      this._runSleepTask(key)
    }, second * 1000)
    return this
  }

  _runImmeadiateTask () {
    this._immediateTask.map(task => {
      typeof task === 'function' && task()
    })
    this._immediateTask = []
  }

  _runSleepTask (key) {
    this._sleepTaskMap[key].map(task => {
      typeof task === 'function' && task()
    })
    this._sleepTaskMap[key] = []
  }

  _log(str) {
    console.log(str)
  }
}

function LazyMan(name) {
  return new LazymanClass(name)
}

const test = () => {
  // LazyMan('Tony')

  // LazyMan('Tony').eat('lunch')

  // LazyMan('Tony').sleep(2).eat('lunch')

  // LazyMan('Tony').eat('lunch').sleep(2).eat('diner')
  
  LazyMan('Tony').eat('lunch').eat('diner').sleepFirst(1).sleep(2).eat('junk food')
}

test()
-梦醒时光 2022-05-04 13:56:26 8 楼
function LazyMan(name){
 return new class LazyMan{
  constructor(name){
   this.tasks=[]
   this.hello(name)
   setTimeout(this.next.bind(this),0)
  }
  log(str){console.log(str);return true}
  next(){
   var fn=this.tasks.shift()
   fn&&fn.apply(this)
  }
  hello(name){
   this.tasks.push(()=>this.log('hello '+name)&&this.next())
   return this
  }
  sleepfirst(time){
   this.tasks.unshift(()=>this.log('sleep '+time)&&setTimeout(this.next.bind(this),time))
   return this
  }
  eat(what){
   this.tasks.push(()=>this.log('eat '+what)&&this.next())
   return this
  }
  sleep(time){
   this.tasks.push(()=>this.log('sleep '+time)&&setTimeout(this.next.bind(this),time))
   return this
  }
 }(name)
}
用心笑* 2022-05-04 13:55:37 7 楼

写个链表实现

class Node {
  constructor(func = null) {
    this.func = func;
    this.next = null;
  }

  async exec() {
    if (this.func) {
      await this.func();
    }
    if (this.next && this.next.func) {
      this.next.exec();
    }
  }
}

function delayFunc(delay) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(`等待了${delay}秒...`);
      resolve();
    }, delay * 1000);
  });
}

class Lazy {
  constructor(name) {
    this.name = name;
    this.head = new Node();
    this.current = this.head;
    Promise.resolve().then(() => this.head.exec());
  }

  eat(sth) {
    const log = () => {
      console.log("I am eating " + sth);
    };
    this.current.next = new Node(log);
    this.current = this.current.next;
    return this;
  }

  sleep(delay) {
    this.current.next = new Node(() => delayFunc(delay));
    this.current = this.current.next;
    return this;
  }

  sleepFirst(delay) {
    let head = new Node(() => delayFunc(delay));
    if (!this.head.func) {
      head.next = this.head.next;
    } else {
      head.next = this.head;
    }
    this.head = head;
    return this;
  }
}

function LazyMan(name) {
  console.log("I am " + name);
  return new Lazy(name);
}

LazyMan('Tony').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food');
故人爱我别走 2022-05-04 13:55:13 6 楼
    function LazyMan(name) {
      console.log("Hi I am Tony");
      return {
        sleepTime: 0,
        firstSleepTime: 0,
        sleep: function(second) {
          let time = 0;
          function logText() {
            setTimeout(() => {
              console.log("等待了十秒...");
            }, time);
          }

          setTimeout(() => {
            time = second * 1000 + this.firstSleepTime * 1000;
            logText();
          }, 0);

          this.sleepTime = this.sleepTime + second;
          return this;
        },
        eat: function(meal) {
          let time = this.sleepTime * 1000;

          function logText() {
            setTimeout(() => {
              console.log("I am eating " + meal);
            }, time);
          }
          setTimeout(() => {
            time = time + this.firstSleepTime * 1000;
            logText();
          }, 0);
          return this;
        },

        sleepFirst: function(second) {
          let time = second * 1000;
          setTimeout(() => {
            console.log("等待了5秒");
          }, time);
          this.firstSleepTime = second;
          return this;
        }
      };
    };
伪装你 2022-05-04 13:54:31 5 楼

Proxy 版本

function LazyMan(username) {
  console.log(' Hi I am ' + username);

  var temp = {
    taskList: [],
    sleepFirst(timeout) {
      return () => {
        setTimeout(() => {
          console.log(`等待了${timeout}秒...`);
          this.next();
        }, timeout * 1000);
      };
    },
    sleep(timeout) {
      return () => {
        setTimeout(() => {
          console.log(`等待了${timeout}秒...`);
          this.next();
        }, timeout * 1000);
      };
    },
    eat(type) {
      return () => {
        console.log(`I am eating ${type}`);
        this.next();
      };
    },
    next() {
      var fn = this.taskList.shift();
      fn && fn();
    }
  };

  var proxy = new Proxy(temp, {
    get(target, key, receiver) {
      return function(...rest) {
        if (key === 'sleepFirst') {
          target.taskList.unshift(target[key](rest));
        } else {
          target.taskList.push(target[key](rest));
        }
        return receiver;
      };
    }
  });

  setTimeout(() => {
    temp.next();
  }, 0);
  return proxy;
}
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
蓬勃野心 2022-05-04 13:49:29 4 楼
class LazyMan {
  constructor(name) {
    this.task = [];
    this.task.push(
      () => {
        console.log(`My name is ${name}`);
        this.next();
      }
    )
    setTimeout(() => { this.next() })
  }
  eat(val) {
    this.task.push(
      () => {
        console.log(`吃 ${val}`);
        this.next();
      }
    )
    return this;
  }
  sleep(sec) {
    this.task.push(
      () => {
        setTimeout(() => {
          console.log(`睡 ${sec} 秒`);
          this.next();
        }, sec * 1000);
      }
    )
    return this;
  }
  next() {
    let fn = this.task.shift();
    fn && fn();
  }
}

let lazyCzh = new LazyMan('czh');
lazyCzh.eat('apple').eat('banana').sleep(3).eat('orange');
雪化。雨蝶 2022-05-04 13:48:18 3 楼
function LazyMan (name) {
  class Man {
   constructor (name) {
     this._queues = []
     console.log(`Hi I am ${name}`)
     Promise.resolve().then(() => {
      this.next()
    })
    return this
   }

   _sleep = (time) => {
     return new Promise(resolve => setTimeout(resolve, time * 1000))
   }

   eat (type) {
     this._queues.push(() => {
       console.log(`I am eating ${type}`)
       this.next();
     })
     return this
   }
   sleepFirst (time) {
     this._queues.unshift(() => {
       this._sleep(time).then(() => {
         console.log(`等待了${time}秒`)
         this.next()
       })
    })
    return this
   }
   
   sleep (time) {
     this._queues.push(() => {
       this._sleep(time).then(() => {
         console.log(`等待了${time}秒`)
        this.next()
      })
     })
     return this
   }

   next () {
     const fn = this._queues.shift();
     fn && fn()
  }
 }

  return new Man(name)
}

LazyMan('Tom');

LazyMan('Tom').sleep(10).eat('lunch')

LazyMan('Tom').eat('lunch').sleep(10).eat('dinner')

LazyMan('Tom').eat('lunch').eat('dinner').sleepFirst(5).sleep(10).eat('junk food')
小嗲 2022-05-04 13:44:08 2 楼
function LazyMan(name){
    var lazy = new Lazy(name);
    lazy.init();
    return lazy;
}
function Lazy(name){
    this.name = name;
    this.fns  = [];
    this.init = function(){
        var _this = this;
        _this.print("I am "+this.name);
        setTimeout(function(){
            _this.next();
        }, 0);
    };
    this.eat = function(food){
        var _this = this;
        _this.fns.push(function(){
            _this.print("I am eating "+food);
            _this.next();
        });
        return this;
    };
    this.sleep= function(time){
        var _this = this;
        _this.fns.push(function(){
            setTimeout(function(){
                _this.print("等待了" + time + "秒");
                _this.next();
            }, 1000*time);
        });
        return this;
    };
    this.sleepFirst = function(time){
        var _this = this;
        _this.fns.unshift(function(){
            setTimeout(function(){
                _this.print("等待了" + time + "秒");
                _this.next();
            }, 1000*time)
        });
        return this;
    };
    this.print = function(something){
        console.log(something);
    };
    this.next = function(){
        this.fns.length>0 && this.fns.shift()();
    };
}
开始看清了 2022-05-02 23:45:29 1 楼
class LazyManClass {
  constructor(name) {
    this.name = name
    this.queue = []
    console.log(`Hi I am ${name}`)
    setTimeout(() => {
      this.next()
    },0)
  }

  sleepFirst(time) {
    const fn = () => {
      setTimeout(() => {
        console.log(`等待了${time}秒...`)
        this.next()
      }, time)
    }
    this.queue.unshift(fn)
    return this
  }

  sleep(time) {
    const fn = () => {
      setTimeout(() => {
        console.log(`等待了${time}秒...`)
        this.next()
      },time)
    }
    this.queue.push(fn)
    return this
  }

  eat(food) {
    const fn = () => {
      console.log(`I am eating ${food}`)
      this.next()
    }
    this.queue.push(fn)
    return this
  }

  next() {
    const fn = this.queue.shift()
    fn && fn()
  }
}

function LazyMan(name) {
  return new LazyManClass(name)
}
~没有更多了~

关于作者

遗失的美好

暂无简介

0 文章
0 评论
0 人气
更多

推荐作者

遥远的她

文章 0 评论 0

情深如许

文章 0 评论 0

18120987591

文章 0 评论 0

女皇必胜

文章 0 评论 0

13002228876

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击“接受”或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。