liuguanyu / quiz-every-meeting

8 stars 0 forks source link

2018-08-09 Event loop #25

Open liuzhengbo opened 6 years ago

liuzhengbo commented 6 years ago

实现一个LazyMan,可以按照以下方式调用:

LazyMan(“Hank”)输出:
Hi! This is Hank!
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
Hi! This is Hank!
//等待10秒..
Wake up after 10
Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
Hi This is Hank!
Eat dinner~
Eat supper~
LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper

以此类推。

mileOfSunshine commented 6 years ago

function LazyMan(name) {

  var tasks = []
  var obj = function() {
    return obj
  }

  function add(task) {
    tasks.push(task)
  }

  function sort() {
    return tasks.sort((a, b) => { 
      return a.weight < b.weight
    })
  }

  function flush() {
    sort()
    tasks.map((task) => {
      task.handler()
    })
  }

  function sleepFn(time) {
    var end = +new Date() + time * 1000
    while(true) {
      var now = +new Date()
      if(now > end) {
        console.log(`Wake up after ${time}`)
        return 
      }
    }
  }

  obj.init = function() {
    add({
      name: 'init',
      weight: 0,
      handler: function() {
        console.log(`Hi! This is ${name}!`)
      }
    })
  }

  obj.sleep = function(time) {
   add({
      name: 'sleep',
      weight: 0,
      handler: function() {
        sleepFn(time)
      }
    })
    return this
  }

  obj.eat = function(something) {
    add({
      name: 'eat',
      weight: 0,
      handler: function() {
        console.log(`Eat ${something}`)
      }
    })
    return this
  }

  obj.sleepFirst = function(time) {
    add({
      name: 'sleepFirst',
      weight: 1,
      handler: function() {
        sleepFn(time)
      }
    })
    return this 
  }

  obj.toString = function() {
    return setTimeout(() => {
      flush()
    })
  }

  obj.init()
  return obj
}
wuxueguang commented 6 years ago
function LazyMan(name) {
    return new LazyMan_(name)
}

function LazyMan_(name) {
    this.tasks = [`sayHi`]
    this.counter = 0
    this.name = name
    this.promise = Promise.resolve().then(() => {
        this._startTasks()
    })
}

LazyMan_.prototype._startTasks = function() {

    let setPromiseOnce = false;
    let ts = this.tasks
    let promiseTaskNames = 'sleep|sleepFirst';
    for (let i = this.counter; i < ts.length; i++) {
        let tmp = ts[i].split('|')

        if (!promiseTaskNames.includes(tmp[0])) {
            this.promise.then(() => {
                let name = `_${tmp[0]}`
                this[name](tmp[1])
            })
        } else if (!setPromiseOnce && promiseTaskNames.includes(tmp[0])) {
            let name = `_${tmp[0]}`
            this[name](tmp[1])          
            setPromiseOnce = true
        } else {
            this.promise.then(() => {
                this._startTasks();
            })
            this.counter = i
            break;
        }
    }
    return this
}

LazyMan_.prototype._addTask = function(name, value) {
    let task = name + (value ? `|${value}` : '')
    this.tasks.push(task);
    return this
}

LazyMan_.prototype._sayHi = function() {
    console.log(`Hi! This is ${this.name}!`)
    return this
}

LazyMan_.prototype.eat = function(sth) {
    this._addTask('eat', sth);
    return this
}

LazyMan_.prototype._eat = function(sth) {
    console.log(`Eat ${sth}`)
    return this
}

LazyMan_.prototype.sleep = function(secondNum) {
    this._addTask('sleep', secondNum)
    return this
}

LazyMan_.prototype.sleepFirst = function(secondNum) {
    this.tasks.unshift(`sleepFirst|${secondNum}`)
    return this
}

LazyMan_.prototype._sleep = function(secondNum) {
    this.promise = new Promise(resolve => {
        setTimeout(resolve, secondNum * 1000)
    })
    this.promise.then(() => console.log(`Wake up after ${secondNum}`))
    return this
}

LazyMan_.prototype._sleepFirst = function(secondNum) {
    return this._sleep(secondNum)
}

LazyMan('Hank').sleep(2).eat('dinner').sleep(3).eat('supper').sleepFirst(1)
chunpu commented 6 years ago
function LazyMan(name) {
  if (!(this instanceof LazyMan)) {
    return new LazyMan(name)
  }
  this.queue = [{value: `Hi! This is ${name}!`}]
  setTimeout(() => { this.next() })
}

Object.assign(LazyMan.prototype, {
  sleep (time) {
    this.queue.push({value: `Wake up after `, delay: time * 1000})
    return this
  },
  sleepFirst (time) {
    this.queue.unshift({value: `Wake up after `, delay: time * 1000})
    return this
  },
  eat (val) {
    this.queue.push({value: `Eat ${val}~`})
    return this
  },
  next () {
    if (this.queue.length) {
      let item = this.queue.shift()
      setTimeout(() => {
        console.log(item.value)
        this.next()
      }, item.delay || 0)
    }
  }
})

LazyMan('Hank').sleepFirst(0.5).eat('supper').sleep(1)
liuguanyu commented 6 years ago
const next = async function () {
  if (this.tasks.length) {
    const task = this.tasks.shift();
    task && await task();
  }
}

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

    this.tasks.push(() => {
      console.log(`Hi! This is ${name}!`);
      next.apply(this);
    });

    setTimeout(() => {
      next.apply(this)
    }, 0)
  }

  eat(food) {
    this.tasks.push(() => {
      console.log(`Eat ${food}~`);
      next.apply(this);
    })
    return this;
  }

  sleep(ts) {
    this.tasks.push(() => {
      setTimeout(() => {
        console.log(`Wake up after ${ts}`);
        next.apply(this);
      }, ts * 1000)
    });
    return this;
  }

  sleepFirst(ts) {
    this.tasks.unshift(() => {
      setTimeout(() => {
        console.log(`Wake up after ${ts}`);
        next.apply(this);
      }, ts * 1000);
    })
    return this;
  }
}

const LazyMan = function (name) {
  return new LazyManImpl(name)
}
tataqiuqiu commented 6 years ago
    function _LazyMan(name) {
        var _this = this;

        _this.fnArray = [];
        var fn =(function(n){
            return function(){
                console.log('Hi! This is ' + n + '!');
                _this.next();
            }
        })(name);
        _this.fnArray.push(fn);
        setTimeout(function(){
            _this.next();
        }, 0);
    }
    _LazyMan.prototype = {
        next: function () {
            var fn = this.fnArray.shift();
            fn && fn();
        },
        eat: function (str) {
            var _this = this;

            var fn = (function(s){
                return function(){
                    console.log('Eat ' + s + '~');
                    _this.next()
                }
            })(str);
            _this.fnArray.push(fn);
            return _this;
        },
        sleep: function (time) {
            var _this = this;

            var fn = (function(t){
                return function(){
                    setTimeout(function(){
                        console.log('Wake up after ' + t);
                        _this.next();
                    }, t * 1000);
                }
            })(time);
            _this.fnArray.push(fn);
            return _this;
        },
        sleepFirst: function (time) {
            var _this = this;
            var fn = (function(t){
                return function() {
                    setTimeout(function() {
                        console.log('Wake up after ' + t);
                        _this.next();
                    }, t * 1000);
                }
            })(time);
            _this.fnArray.unshift(fn);
            return _this;
        }
    }

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

    LazyMan('Hank').sleep(2).eat('dinner')