# 手写发布订阅

问题 发布订阅、EventEmitter

# 发布订阅的优点

  • 可以广泛用于异步编程,可以替换传统的回调函数
  • 无需关注异步操作的内部状态,只需要关注事件完成的节点
  • 取代对象之间硬编码通知机制,一个对象不必显式地去调用另一个对象的接口,而是松耦合的联系在一起

# NodeJS中的EventEmitter

NodejsEventEmitter是观察者模式的典型实现,Nodejsevents模块只提供了一个对象: events.EventEmitter webpack  的插件机制核心库 tapable  也是发布订阅模式的典型实现。**

# 实现

  • addListener(event, listener)
  • removeListener(event, listener)
  • setMaxListeners(n)
  • once(event, listener)
  • emit(event, [arg1], [arg2], [...])
function EventEmitter() {
      this._maxListeners = 10;
      this._events = Object.create(null);
    }

    // 向事件队列添加事件
    // prepend为true表示向事件队列头部添加事件
    EventEmitter.prototype.addListener = function (type, listener, prepend) {
      if (!this._events) {
        this._events = Object.create(null);
      }
      if (this._events[type]) {
        if (prepend) {
          this._events[type].unshift(listener);
        } else {
          this._events[type].push(listener);
        }
      } else {
        this._events[type] = [listener];
      }
    };

    // 移除某个事件
    EventEmitter.prototype.removeListener = function (type, listener) {
      if (Array.isArray(this._events[type])) {
        if (!listener) {
          delete this._events[type]
        } else {
          this._events[type] = this._events[type].filter(e => e !== listener && e.origin !== listener)
        }
      }
    };

    // 向事件队列添加事件,只执行一次
    EventEmitter.prototype.once = function (type, listener) {
      const only = (...args) => {
        listener.apply(this, args);
        this.removeListener(type, listener);
      }
      only.origin = listener;
      this.addListener(type, only);
    };

    // 执行某类事件
    EventEmitter.prototype.emit = function (type, ...args) {
      if (Array.isArray(this._events[type])) {
        this._events[type].forEach(fn => {
          fn.apply(this, args);
        });
      }
    };

    // 设置最大事件监听个数
    EventEmitter.prototype.setMaxListeners = function (count) {
      this.maxListeners = count;
    };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Last Updated: 10/29/2020, 1:21:25 AM