AymaxLi / AymaxLi.github.io

:point_right: my blog,show in issues ~

Home Page:https://github.com/AymaxLi/AymaxLi.github.io/issues

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

手撸一个事件订阅器

AymaxLi opened this issue · comments

commented

代码

function EventEmitter() {
  // 依赖队列集
  this.dep = {
    // name1: [{
    //   once: true,
    //   fn: fn
    // }],
    // name2: [{
    //   once: true,
    //   fn: fn
    // }]
  }
}

EventEmitter.prototype.on = function (name, fn, once) {
  var obj = {
    fn,
    once: once || false // 是否为 once,默认为 false
  }

  this.dep[name] ? this.dep[name].push(obj) : this.dep[name] = [obj] // 是否存在事件 name 的依赖队列,是则 push ,否则新建一个数组
}

EventEmitter.prototype.once = function (name, fn) {
  this.on(name, fn, true)
}

EventEmitter.prototype.emit = function (name) {
  var args = Array.prototype.slice.call(arguments, 1)
  var onceArr = [] // 记录这次事件中 once 的函数

  this.dep[name].forEach((el, index) => {
    el.fn.apply(null, args) // 执行函数
    // 假如是 once ,标记
    if (el.once === true) onceArr.push(index)
  })

  // 移除 once 的函数
  onceArr.forEach(index => this.dep[name].splice(index, 1))
}

EventEmitter.prototype.remove = function (name, fn) {
  var index = this.dep[name].findIndex(el => el.fn.name === fn.name) // 找到要 remove 的函数的下标

  this.dep[name].splice(index, 1) // 移除
}
commented

测试用例

const sayOne = _ => console.log('one')
const sayTwo = _ => console.log('two')
const sayNo = _ => console.log('no')

// 测试 emit
;(_ => {
  var e = new EventEmitter()

  e.on('haha', console.log)
  e.emit('haha', 'hei i am aymax')
})()

// 测试 once
;(_ => {
  var e = new EventEmitter()

  e.on('haha', sayOne)
  e.on('haha', sayTwo)
  e.once('haha', sayNo)

  e.emit('haha')
  e.emit('haha')
})()

// 测试 remove
;(_ => {
  var e = new EventEmitter()

  e.on('haha', sayOne)
  e.on('haha', sayTwo)
  e.once('haha', sayNo)

  e.remove('haha', sayNo)

  e.emit('haha')

  e.remove('haha', sayOne)

  e.emit('haha')
})()