/**
 * @Author: 王林
 * @Date: 2021-06-27 13:16:23
 * @Desc: 在下一个事件循环里执行任务
 */
const nextTick = function (fn, ctx) {
  let pending = false
  let timerFunc = null
  let handle = () => {
    pending = false
    ctx ? fn.call(ctx) : fn()
  }
  // 支持MutationObserver接口的话使用MutationObserver
  if (typeof MutationObserver !== 'undefined') {
    let counter = 1
    let observer = new MutationObserver(handle)
    let textNode = document.createTextNode(counter)
    observer.observe(textNode, {
      characterData: true // 设为 true 表示监视指定目标节点或子节点树中节点所包含的字符数据的变化
    })
    timerFunc = function () {
      counter = (counter + 1) % 2 // counter会在0和1两者循环变化
      textNode.data = counter // 节点变化会触发回调handle，
    }
  } else {
    // 否则使用定时器
    timerFunc = setTimeout
  }
  return function () {
    if (pending) return
    pending = true
    timerFunc(handle, 0)
  }
}

/**
 * @Author: 王林
 * @Date: 2021-06-26 22:40:52
 * @Desc: 批量执行
 */
class BatchExecution {
  /**
   * @Author: 王林
   * @Date: 2021-06-26 22:41:41
   * @Desc: 构造函数
   */
  constructor() {
    this.has = {}
    this.queue = []
    this.nextTick = nextTick(this.flush, this)
  }

  /**
   * @Author: 王林
   * @Date: 2021-06-27 12:54:04
   * @Desc: 添加任务
   */
  push(name, fn) {
    if (this.has[name]) {
      return
    }
    this.has[name] = true
    this.queue.push({
      name,
      fn
    })
    this.nextTick()
  }

  /**
   * @Author: 王林
   * @Date: 2021-06-27 13:09:24
   * @Desc:  执行队列
   */
  flush() {
    let fns = this.queue.slice(0)
    this.queue = []
    fns.forEach(({ name, fn }) => {
      this.has[name] = false
      fn()
    })
  }
}

export default BatchExecution
