Skip to content

实现 event模块

Posted on:2021年7月7日 at 00:13

实现node中回调函数的机制,node中回调函数其实是内部使用了观察者模式。

观察者模式:定义了对象间一种一对多的依赖关系,当目标对象Subject发生改变时,所有依赖它的对象Observer都会得到通知。


function EventEmitter() {
  this.events = new Map();
}

// 需要实现的一些方法:
// addListener、removeListener、once、removeAllListeners、emit

// 模拟实现addlistener方法
const wrapCallback = (fn, once = false) => ({ callback: fn, once });
EventEmitter.prototype.addListener = function (type, fn, once = false) {
  const hanlder = this.events.get(type);
  if (!hanlder) {
    // 没有type绑定事件
    this.events.set(type, wrapCallback(fn, once));
  } else if (hanlder && typeof hanlder.callback === "function") {
    // 目前type事件只有一个回调
    this.events.set(type, [hanlder, wrapCallback(fn, once)]);
  } else {
    // 目前type事件数>=2
    hanlder.push(wrapCallback(fn, once));
  }
};
// 模拟实现removeListener
EventEmitter.prototype.removeListener = function (type, listener) {
  const hanlder = this.events.get(type);
  if (!hanlder) return;
  if (!Array.isArray(this.events)) {
    if (hanlder.callback === listener.callback) this.events.delete(type);
    else return;
  }
  for (let i = 0; i < hanlder.length; i++) {
    const item = hanlder[i];
    if (item.callback === listener.callback) {
      hanlder.splice(i, 1);
      i--;
      if (hanlder.length === 1) {
        this.events.set(type, hanlder[0]);
      }
    }
  }
};
// 模拟实现once方法
EventEmitter.prototype.once = function (type, listener) {
  this.addListener(type, listener, true);
};
// 模拟实现emit方法
EventEmitter.prototype.emit = function (type, ...args) {
  const hanlder = this.events.get(type);
  if (!hanlder) return;
  if (Array.isArray(hanlder)) {
    hanlder.forEach((item) => {
      item.callback.apply(this, args);
      if (item.once) {
        this.removeListener(type, item);
      }
    });
  } else {
    hanlder.callback.apply(this, args);
    if (hanlder.once) {
      this.events.delete(type);
    }
  }
  return true;
};
EventEmitter.prototype.removeAllListeners = function (type) {
  const hanlder = this.events.get(type);
  if (!hanlder) return;
  this.events.delete(type);
};
原文转自:https://fe.ecool.fun/topic/3d3c752d-f969-44ce-acaf-18e43d52f069