• Nodejs核心模块之Events


    核心模块之Events

    通过EventEmitter类实现事件统一管理

    events与EventEmitter

    • node.js是基于事件驱动的异步操作架构,内置events模块
    • events模块提供了EventEmitter类
    • node.js中很多内置核心模块集成EventEmitter

    EventEmitter常见Api

    • on
      • 添加实现被触发时调用的回调函数
    const EventEmitter = require('events')
    const ev = new EventEmitter()
    // on 
    ev.on('事件1', () => {
      console.log('事件1执行了---2')
    })
    ev.on('事件1', () => {
      console.log('事件1执行了')
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • emit
      • 出发事件,按照注册的顺序同步调用每个事件监听器
    // emit触发
    ev.emit('事件1')
    
    • 1
    • 2
    • once
      • 添加当事件在注册之后首次被触发时调用的回调函数
    ev.once('事件1', () => {
      console.log('事件1执行了')
    })
    ev.once('事件1', () => {
      console.log('事件1执行了--2')
    })
    
    ev.emit('事件1')
    ev.emit('事件1')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • off
      • 移除特定的监听器
    let cbFn = (...args) => {
      console.log(args)
    }
    ev.on('事件1', cbFn) 
    ev.emit('事件1')
    // 移除
    ev.off('事件1', cbFn)
    ev.emit('事件1', 1, 2, 3)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    发布订阅

    • 缓存队列,存放订阅者消息
    • 具有增加和删除订阅的能力
    • 状态改变时通知所有订阅者执行监听
    • 发布订阅存在一个调度中心,而观察者中是不存在的
    • 状态发生改变时,发布订阅无须主动通知订阅者
      在这里插入图片描述
    class PubSub{
      constructor() {
        this._events = {}
      }
    
      // 注册
      subscribe(event, callback) {
        if (this._events[event]) {
          // 如果当前 event 存在,所以我们只需要往后添加当前次监听操作
          this._events[event].push(callback)
        } else {
          // 之前没有订阅过此事件
          this._events[event] = [callback]
        }
      }
    
      // 发布
      publish(event, ...args) {
        const items = this._events[event]
        if (items && items.length) {
          items.forEach(function (callback) {
            callback.call(this, ...args)
          })
        }
      }
    }
    
    let ps = new PubSub()
    ps.subscribe('事件1', () => {
      console.log('事件1执行了')
    })
    ps.subscribe('事件1', () => {
      console.log('事件1执行了---2')
    })
    
    ps.publish('事件1')
    ps.publish('事件1')
    
    • 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

    EventEmitter模拟

    function MyEvent () {
      // 准备一个数据结构用于缓存订阅者信息
      this._events = Object.create(null)
    }
    
    MyEvent.prototype.on = function (type, callback) {
      // 判断当前次的事件是否已经存在,然后再决定如何做缓存
      if (this._events[type]) {
        this._events[type].push(callback)
      } else {
        this._events[type] = [callback]
      }
    }
    
    MyEvent.prototype.emit = function (type, ...args) {
      if (this._events && this._events[type].length) {
        this._events[type].forEach((callback) => {
          callback.call(this, ...args)
        })
      }
    }
    
    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
        })
      }
    }
    
    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)
    }
    
    let ev = new MyEvent()
    
    let fn = function (...data) {
      console.log('事件1执行了', data)
    }
    
    ev.once('事件1', fn)
    // ev.off('事件1', fn)
    ev.emit('事件1', '前')
    
    • 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
  • 相关阅读:
    基于最近电平逼近的开环MMC逆变器MATLAB仿真模型
    进入Mysql数据库操作
    【Python】类与实例(20)
    简单整理一下vue2和vue3【一】
    python与自然语言处理3朴素贝叶斯
    前端学习地址_备忘录(随时更新)
    喜报 | AR 开启纺织产业新模式,ALVA Systems 再获殊荣!
    Java面试进阶指北
    JS 中防抖函数形成闭包的相关处理及思考
    Figma 怎么切图?新手入门教程详解
  • 原文地址:https://blog.csdn.net/qq_42308316/article/details/127999156