zoukankan      html  css  js  c++  java
  • JS的发布订阅模式

    JS的发布订阅模式

    这里要说明一下什么是发布-订阅模式

    • 发布-订阅模式里面包含了三个模块,发布者,订阅者和处理中心。这里处理中心相当于报刊办事大厅。发布者相当与某个杂志负责人,他来中心这注册一个的杂志,而订阅者相当于用户,我在中心订阅了这分杂志。每当发布者发布了一期杂志,办事大厅就会通知订阅者来拿新杂志。这样在结合下面的图应该很好理解了。
      发布订阅图1
    • 其实就是将发布者和订阅者解耦了,在实际开发中,经常会遇到某个方法内处理很多的逻辑,最简单的就是直接在方法内直接写。这种是高度耦合的面向过程的写法。对于代码维护不友好。而发布-订阅模式就是将两者分离。我触发了某个事件(这里我们将触发该方法定义为事件),我只向调度中心通知,我并不知道调度中心内会怎么处理,有多少个人响应。我只管通知。而订阅者只管在调度中心订阅,有人调用它才响应。
    • 还有一点就是假设我们有3个js文件,事件触发在a.js内,而响应该事件的在b.js和c.js内,要是用常规调用的方法的话,就要把b.js和c.js的方法传到a.js内。这是一个非常麻烦的操作。而发布-订阅模式是将调度中心挂在了全局,我们只管调用调度中心相应的方法注册和订阅。

    ps:还有一点要注意的,很多人会把观察者模式和发布-订阅模式混淆,其实两者之间还是有点区别的,不过在本文我不会详细讲。

    下面我们来实现一个发布-订阅模式的类

    class Event {
      constructor () {}
      // 首先定义一个事件容器,用来装事件数组(因为订阅者可以是多个)
      handlers = {}
    
      // 事件添加方法,参数有事件名和事件方法
      addEventListener (type, handler) {
        // 首先判断handlers内有没有type事件容器,没有则创建一个新数组容器
        if (!(type in this.handlers)) {
          this.handlers[type] = []
        }
        // 将事件存入
        this.handlers[type].push(handler)
      }
    
      // 触发事件两个参数(事件名,参数)
      dispatchEvent (type, ...params) {
        // 若没有注册该事件则抛出错误
        if (!(type in this.handlers)) {
          return new Error('未注册该事件')
        }
        // 便利触发
        this.handlers[type].forEach(handler => {
          handler(...params)
        })
      }
    
      // 事件移除参数(事件名,删除的事件,若无第二个参数则删除该事件的订阅和发布)
      removeEventListener (type, handler) {
          // 无效事件抛出
          if (!(type in this.handlers)) {
            return new Error('无效事件')
          }
          if (!handler) {
            // 直接移除事件
            delete this.handlers[type]
          } else {
            const idx = this.handlers[type].findIndex(ele => ele === handler)
            // 抛出异常事件
            if (idx === -1) {
              return new Error('无该绑定事件')
            }
            // 移除事件
            this.handlers[type].splice(idx, 1)
            if (this.handlers[type].length === 0) {
              delete this.handlers[type]
            }
          }
        }
    }
    

    ok到现在为止就已经实现了基本发布订阅的功能了,其实很简单,如果还有什么奇怪的需求,都可以通通往里面加。

    下面是完整的使用demo

    var event = new Event() // 创建event实例
    // 定义一个自定义事件:"load"
    function load (params) {
      console.log('load', params)
    }
    event.addEventListener('load', load)
    // 再定义一个load事件
    function load2 (params) {
      console.log('load2', params)
    }
    event.addEventListener('load', load2)
    // 触发该事件
    event.dispatchEvent('load', 'load事件触发')
    // 移除load2事件
    event.removeEventListener('load', load2)
    // 移除所有load事件
    event.removeEventListener('load')
    

    希望大家转载时注明出处:https://www.cnblogs.com/suyuanli/p/9655699.html

  • 相关阅读:
    高仿爱鲜蜂购物应用源码
    控制ClistCtrl的滚动的位置
    VC保存当面某个区域的图片
    MFC 屏幕截图方法
    回调函数使用(三)
    回调函数使用方法二
    VS2010编译Boost 1.57 静态链接库
    Windows7+VS2010下OpenGL的环境配置
    CxImage图像库的使用 .
    VS2010+PCL配置
  • 原文地址:https://www.cnblogs.com/suyuanli/p/9655699.html
Copyright © 2011-2022 走看看