阅读 63

发布订阅模式

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

什么是发布订阅模式

发布订阅模式定义了一种 一对多 的依赖关系,一是指发布者,负责发布事件,多是指订阅者,可以有多个订阅者订阅某一个事件。当事件触发的时候,订阅者获得通知。

发布订阅模式广泛存在于前端变成,比如事件触发,vue组件生命周期的触发,vue watch触发,nodejs里的事件处理。

发布订阅模式旨在降低系统不同模块之间的耦合度,在各自内部模块互相不耦合。

实现

基本实现

class EventBus {
  constructor() {
    this.obj = {}
  }
  on(key, fn) {
    this.obj[key] = fn;
  }
  emit(key, value) {
    this.obj[key].call(this, value);
  }
}

let eventBus = new EventBus();
// 订阅一个name为test1的事件
eventBus.on('test1', (val) => {
  console.log('test1', 'value:' + val)
});
// 订阅一个name为test2的事件
eventBus.on('test2', function (val) {
  console.log('test2', 'value:' + val)
});

setTimeout(() => {
  // 触发test1
  eventBus.emit('test1', 1)
  // 触发test2
  eventBus.emit('test2', 2)
}, 1000)
复制代码

进一步优化:支持多个订阅者

class EventBus {
  constructor() {
    this.obj = {}
  }
  on(key, fn) {
    if(this.obj[key] === undefined){
      this.obj[key] = []
    }
    this.obj[key].push(fn)
  }
  emit(key, value) {
    this.obj[key].map(fn=>{
      fn.call(this, value);
    })
  }
}

let eventBus = new EventBus();
// 订阅一个name为test1的事件
eventBus.on('test1', (val) => {
  console.log('test1', 'value:' + val+ ' 1')
});
eventBus.on('test1', (val) => {
  console.log('test1', 'value:' + val + ' 2')
});
// 订阅一个name为test2的事件
eventBus.on('test2', function (val) {
  console.log('test2', 'value:' + val)
});

setTimeout(() => {
  // 触发test1
  eventBus.emit('test1', 1)
  // 触发test2
  eventBus.emit('test2', 2)
}, 1000)
复制代码

再一步优化:支持取消事件订阅

class EventBus {
  constructor() {
    this.obj = {}
  }
  on(key, fn) {
    if(this.obj[key] === undefined){
      this.obj[key] = []
    }
    this.obj[key].push(fn)
  }
  emit(key, value) {
    this.obj[key].map(fn=>{
      fn.call(this, value);
    })
  }
  off(key,value){
    if(typeof value === 'function' && this.obj[key]){
      const index = this.obj[key].findIndex(fn=>fn === value)
      if(index !== -1){
        this.obj[key].splice(index)
      }
    }
  }
}

let eventBus = new EventBus();
// 订阅一个name为test1的事件

const fn1 = (val) => {
  console.log('test1', 'value:' + val + ' 1')
}
eventBus.on('test1', fn1);
eventBus.on('test1', (val) => {
  console.log('test1', 'value:' + val + ' 2')
});
;
// 订阅一个name为test2的事件
eventBus.on('test2', function (val) {
  console.log('test2', 'value:' + val)
});

setTimeout(() => {
  // 触发test1
  eventBus.emit('test1', 1)
  // 触发test2
  eventBus.emit('test2', 2)

  eventBus.off('test1', fn1)

  eventBus.emit('test1', 1)

}, 1000)
复制代码

参考资料

  1. juejin.cn/post/684490…
  2. juejin.cn/post/685041…
  3. juejin.cn/post/684490…
文章分类
前端
文章标签