JS中的异步链式调用

let EatMan = function () {
  this.task = [] // 声明一个task数组,模拟事件循环队列;
  this.taskNum = []
  let fn = () => {
    this.next();
  }
  this.task.push(fn);
  setTimeout(() => {
    this.next();
  }, 0)
  return this;
}

EatMan.prototype.eat = function (str) { // 为了task任务队列一致性,将eat也转换为setTimeout异步
  const _this = this
  var fn = () => {
    setTimeout(() => {
      console.log(str)
      _this.next()
    }, 0)
  }
  this.task.push(fn)
  this.taskNum.push(str)
  return this // 返回this使得可以链式操作
}
EatMan.prototype.sleep = function (ms) { // setTimeout的任务,需要在完成时再调用next继续执行
  const _this = this
  var fn = () => {
    setTimeout(() => {
      console.log('this is normal sleep.')
      _this.next()
    }, ms * 1000)
  }
  this.task.push(fn)
  this.taskNum.push('sleep')
  return this
}
EatMan.prototype.firstSleep = function (ms) { // 与sleep类似,注意需要在队首加入
  const _this = this
  var fn = () => {
    setTimeout(() => {
      console.log('this is first sleep.')
      _this.next()
    }, ms * 1000)
  }
  this.task.unshift(fn)
  this.taskNum.unshift('firstSleep')
  return this
}
EatMan.prototype.next = function () { // 通过next指针完成出队列操作,使之拥有顺序
  let fn = this.task.shift()
  fn && fn()
}

let eatMan = new EatMan()
eatMan.eat('apple').eat('orange').sleep(3).eat('banana').firstSleep(3)
console.log(eatMan.taskNum)