Node events

304 阅读1分钟

events 又称事件触发器,使用者可以触发某个事件events.emit('eventName')并执行该事件的回调队列

构造函数

触发器要执行回调就要管理回调队列

// 触发器构造函数
function EventEmitter() {
  // 触发器实例管理多个事件回调队列
  this._events = {}
}

事件回调注册方法(on)

将回调方法放入某个事件的回调队列中

/**
 * 事件回调注册方法
 * @param {string} eventName - 事件名称
 * @param {Function} callback - 事件回调
 */
EventEmitter.prototype.on = function (eventName, callback) {
  if (!this._events) {
    this._events = {}
  }

  // 添加回调触发内部事件
  if (eventName !== 'newListener') {
    if (this._events['newListener']) {
      this.emit('newListener', eventName)
    }
  }

  // 将回调存入缓存中
  let callbacks = this._events[eventName] || []
  callbacks.push(callback)
  this._events[eventName] = callbacks
}

事件发射方法

执行该事件回调队列中的方法

/**
 * 事件发射方法
 * @param {string} eventName - 事件名称
 * @param  {...any} args - 参数列表
 */
EventEmitter.prototype.emit = function (eventName, ...args) {
  if (this._events[eventName]) {// 遍历执行事件回调
    this._events[eventName].forEach(fn => {
      fn(...args)
    })
  }
}

注册只触发一次的回调

执行完回调后将回调方法从队列中删除

/**
 * 注册只触发一次的回调
 * @param {string} eventName - 事件名称
 * @param {Function} callback - 事件回调
 */
EventEmitter.prototype.once = function (eventName, callback) {
  // 对回调进行包装,执行后将自己从回调队列中删除
  const one = () => {
    callback()
    this.off(eventName, one)
  }
  // 暴露出原回调方法,便于删除
  one.l = callback
  this.on(eventName, one)
}

删除某个事件回调的方法

能找到要删除的回调就能删除

/**
 * 删除某个事件回调的方法
 * @param {string} eventName - 事件名称
 * @param {Function} callback - 回调方法
 */
EventEmitter.prototype.off = function (eventName, callback) {
  if (this._events[eventName]) {
    this._events[eventName] = this._events[eventName].filter(event => {
      return event !== callback && event.l !== callback
    })
  }
}