发布订阅模式

  1. 发布订阅模式分为:订阅者、发布者、信号中心
    • 假定,存在一个 “信号中心”,某个任务执行完成,就向信号中心 “发布” (publish) 一个信号;
    • 其他任务可以向信号中心 “订阅” (subscribe) 这个信号,从而知道什么时候自己可以开始执行;
    • 订阅和发布没有任明显关系,主要靠信号中心关联;
  2. 这就叫做 “发布/订阅式” (publish-subscribepattern)

应用场景

  1. Vue的自定义事件

    // Vue 自定义事件
    let vm = new Vue()
    
    // { 'click': [fn1, fn2], 'change': [fn] }
    // 注册事件(订阅消息)
    vm.$on('dataChange', () => {
      console.log('dataChange')
    })
    vm.$on('dataChange', () => {
      console.log('dataChange1')
    })
    
    // 触发事件(发布消息)
    vm.$emit('dataChange')
    
  2. 兄弟组件通信过程(也叫事件总线)

    // eventBus.js 
    // 事件中心 
    let eventHub = new Vue()
    
    // ComponentA.vue 
    // 发布者 addTodo: 
    function () {
      // 发布消息(事件) 
      eventHub.$emit('add-todo', {text: this.newTodoText }) 
      this.newTodoText = ''
    }
    
    // ComponentB.vue 
    // 订阅者 
    created: function () {
      // 订阅消息(事件) 
      eventHub.$on('add-todo', this.addTodo)
    }
    

模拟 Vue 自定义事件的实现

// 事件触发器
class EventEmitter {
  constructor() {
    // 信号中心:{ 'click': [fn1, fn2], 'change': [fn] }
    this.subs = Object.create(null) // 创建一个没有原型属性的 object,性能要好一点
  }

  // 订阅通知
  $on(eventType, handler) {
    this.subs[eventType] = this.subs[eventType] || []
    this.subs[eventType].push(handler)
  }

  // 发布通知
  $emit(eventType) {
    if (this.subs[eventType]) {
      this.subs[eventType].forEach(handler => {
        handler()
      })
    }
  }
}

// 测试
let em = new EventEmitter()
//注册事件
em.$on('click', () => {
  console.log('click1')
})
em.$on('click', () => {
  console.log('click2')
})
//触发事件
em.$emit('click')

观察者模式

  1. 观察者(订阅者) – Watcher

    • update():当事件发生时,具体要做的事情;
  2. 目标(发布者) – Dep

    • subs 数组:收集所有的观察者;
    • addSub():添加观察者;
    • notify():当事件发生,调用所有观察者的 update() 方法;
  3. 实现代码

    // 目标(被观察者)
    class Dep {
      constructor() {
        // 收集所有的观察者 watcher
        this.subs = []
      }
      // 添加订阅者
      addSub(watcher) {
        if (watcher&& watcher.update) {
          this.subs.push(watcher)
        }
      }
      // 发布通知
      notify() {
        this.subs.forEach(watcher => {
          watcher.update()
        })
      }
    }
    
    // 观察者
    class Watcher {
      update() {
        console.log('update')
      }
    }
    
    // 测试
    let dep = new Dep()
    let watcher = new Watcher()
    dep.addSub(watcher)
    dep.notify()
    

观察者 VS 发布订阅

  1. 观察者模式:是由具体目标调度,比如当事件触发,Dep 就会去调用观察者的方法,所以观察者模式的订阅者与发布者之间是存在依赖的;

  2. 发布/订阅模式:由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在,这样一方面实现了解耦,还可以实现更细粒度的一些控制,比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以在调度中心做一些处理,类似于权限控制之类的;还可以做一些节流操作;

  3. 对比图:

打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于前端开发的技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程。

了解更多

目录

  1. 1. 发布订阅模式
    1. 1.1. 应用场景
    2. 1.2. 模拟 Vue 自定义事件的实现
  2. 2. 观察者模式
  3. 3. 观察者 VS 发布订阅