• 通过EventEmitter类实现事件统一管理
  • 实际开发中,用的较少,因为很多模块已经继承了这个类

    events与EventEmitter

  • nodejs是基于事件驱动的异步操作架构,内置events模块

  • events模块提供了EventEmitter类
  • nodejs中很多内置核心模块继承了EventEmitter,例如FS http

    EventEmittr常见API

  • on: 添加当事件被触发时调用的回调函数

  • emit: 触发事件,按照注册的顺序同步调用每个事件监听器,(第二个参数可以传参)
  • once:添加当事件在注册之后首次被触发时调用的回调函数,调用后会被删除掉 ```javascript const EventEmitter = require(‘events’)

const ev = new EventEmitter() // 执行顺序是注册时的顺序 // 1. on ev.on(‘事件1’,() => { console.log(‘事件1执行了’); })

ev.on(‘事件1’,() => { console.log(‘事件1执行了—-2’); })

// emit 多次触发多次执行 ev.emit(‘事件1’) ev.emit(‘事件1’)


// 2. once ev.once(‘事件1’,() => { console.log(‘事件1 once执行了’); }) ev.once(‘事件1’,() => { console.log(‘事件1 once执行了’); }) ev.emit(‘事件1’) // ev.emit(‘事件1’) 第二次监听,不执行,因为删掉了

// 3. off 删除事件 let cbFn = (…args) => { console.log(“事件1执行”); console.log(args); }; ev.on(“事件1”, cbFn);

// 传参 ev.emit(“事件1”, 1, 2);

// ev.off(“事件1”, cbFn); ev.emit(“事件1”, 1, 2);


ev.on(“事件1”, function () { console.log(this); }); ev.on(“事件2”, function () { console.log(this); }); /* EventEmitter { _events: [Object: null prototype] { ‘事件1’: [Function (anonymous)], ‘事件2’: [Function (anonymous)] }, _eventsCount: 2, _maxListeners: undefined,

} */

// 相同的事件,有多少个事件监听,_events数组中就会加多少个 ev.emit(“事件1”); ev.emit(“事件2”);

const fs = require(‘fs’) const crt = fs.createReadStream() crt.on(‘data’)

  1. <a name="u8ZoW"></a>
  2. ### 发布订阅模式
  3. - 是一个模型,定义了对象间一对多的依赖关系,不同对象间实现了解耦,完全做到不认识彼此
  4. - 发布订阅可以解决什么问题?
  5. - 答案:连续使用多个异步API, 这些异步又互相依赖彼此的执行结果,这个时候会产生很多回调嵌套,发布订阅模式很好做好
  6. - NodeJs中的event loop中的事件队列
  7. - 发布订阅要素
  8. - 缓存队列,存放订阅者信息
  9. - 具有增加、删除订阅的能力
  10. - 状态改变时通知所有订阅者执行监听
  11. - 发布订阅模式和观察者模式区别
  12. - 发布订阅中存在调度中心(观察者模式中没有)
  13. - 状态发生改变时,发布订阅无须主动通知(由调度中心决定订阅之前的信息如何执行)
  14. ![发布订阅模式.png](https://cdn.nlark.com/yuque/0/2022/png/22628793/1651569406062-66884868-a152-4aff-bce9-7b0c8e6092e4.png#clientId=u7fdd22fa-7fcf-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=u350cf1f4&margin=%5Bobject%20Object%5D&name=%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85%E6%A8%A1%E5%BC%8F.png&originHeight=476&originWidth=933&originalType=binary&ratio=1&rotation=0&showTitle=false&size=99980&status=done&style=none&taskId=u150aa13f-0d48-464d-8ba9-10493f43100&title=)
  15. ```javascript
  16. class PubSub {
  17. constructor() {
  18. this._events = {};
  19. }
  20. // 注册
  21. subscribe(event, callback) {
  22. // 查找监听是否存在
  23. if (this._events[event]) {
  24. // 如果event存在,所以我们只需要往后添加当前次监听操作
  25. this._events[event].push(callback);
  26. } else {
  27. // 之前没有订阅过次事件,创建数组,放入事件
  28. this._events[event] = [callback];
  29. }
  30. }
  31. // 发布,发布哪个事件,传入参数
  32. publish(event, ...args) {
  33. const items = this._events[event];
  34. if (items && items.length) {
  35. items.forEach((callback) => {
  36. // 绑定this, 传入参数
  37. callback.call(this, ...args);
  38. });
  39. }
  40. }
  41. }
  42. let ps = new PubSub()
  43. ps.subscribe('事件1',() => {
  44. console.log('事件1 执行了');
  45. })
  46. ps.subscribe('事件2',() => {
  47. console.log('事件2 执行了');
  48. })
  49. ps.publish('事件1')
  50. ps.publish('事件2')

EventEmitter模拟

function MyEvent() {
  // 准备一个数据结构用于缓存订阅者的一些信息
  this._events = Object.create(null); // 创建不带任何原型的空对象
}

// on 操作实现
MyEvent.prototype.on = function (type, callback) {
  // 判断当前次的事件是否已经存在
  if (this._events[type]) {
    this._events[type].push(callback);
  } else {
    this._events[type] = [callback];
  }
};

// emit事件实现
MyEvent.prototype.emit = function (type, ...args) {
  if (this._events && this._events[type].length) {
    this._events[type].forEach((callback) => {
      callback.call(this, ...args);
    });
  } else {
  }
};

// off取消事件监听
MyEvent.prototype.off = function (type, callback) {
  // 先判断当前type事件监听是否存在,如果存在则取消指定的监听
  if (this._events && this._events[type]) {
    this._events[type] = this._events[type].filter((item) => {
      return item !== callback && item.link !== callback;
      // 判断一下当前回调和item的link(once函数里面建立一层关系)是否一样,如果一样那就过滤掉   留下不被取消的
    });
  }
};

// once
MyEvent.prototype.once = function (type, callback) {
  let foo = function (...args) {
    callback.call(this, ...args);
    this.off(type, foo); // 执行完取消掉这个函数
  };
  // 建立一层关系
  foo.link = callback
  // 先触发,再取消
  this.on(type, foo);
  //   this.off(type, callback);
};

let ev = new MyEvent();
let fn = function (...data) {
  console.log("事件1执行了");
  console.log(data);
};

// ev.on('事件1', fn)
// ev.on('事件1', () => {
//     console.log('事件1');
// })

// ev.emit('事件1',1,2)
// ev.emit('事件1',1,2)

ev.once("事件1", fn);
ev.off("事件1", fn);
ev.emit("事件1", "前");
// ev.emit("事件1", "前1"); // once第二次不生效的
// ev.off("事件1", fn); // 取消了事件1监听
// ev.emit("事件1", "后");