简单实现 发布订阅模式

83 阅读3分钟

实现一个发布订阅模式

基本方法

on():注册事件;也就是该模式中的发布;

emit():触发事件;该模式中的订阅;

once():注册只能触发一次的事件;触发后即被删除;

off():删除指定已注册事件;

优缺点

优点

广泛应用于异步编程,可以代替传统的回调函数,只需要关注事件完成的时间点;

时间上解耦,对象间解耦;

(耦合:对象间的耦合度就是对象之间的依赖性,耦合度越高,维护成本就越高;

解耦:接触耦合关系)

缺点

创建订阅者会消耗一定内存;

过度使用会导致代码难以维护;

代码

class EventEmitter{
  constructor(){
    //存放事件
    this.cache = {}
  }
  
  // 注册事件
  on(name,func){
    const tasks = this.cache[name]
    // 判断cache中是否有name事件的回调数组
    if(tasks){
      // 有则把func存进数组中
      this.cache[name].push(func)
    }else{
      // 没有则创建一个数组,并把func放到其中
      this.cache[name] = [func]
    }
  }
  
  // 移除事件
  off(name,func){
    const tasks = this.cache[name]
    if(tasks){
      //查找cache的name事件的回调数组是否存在func,并返回索引值给index
      const index = tasks.findIndex(item => item === func)
      if(index >= 0){
        //有则使用splice从index位置开始删除一个元素
        this.cache[name].splice(index,1)
      }
    }
  }
  
  //触发事件
  emit(name, ...args){
    //浅拷贝到tasks
    const tasks = this.cache[name].slice()
    //判断一下是否存在
    if(tasks){
      //存在即循环tasks执行func,参数为传进的args
      for(let func of tasks){
        func(...args)
      }
    }
  }
  
  // 注册只能调用一次的事件
  once(name,cb){
    //定义一个方法func用于注册
    //一旦被调用即执行callback函数和off函数删除事件
    function func(...args){
      cb(args)
      this.off(name,func)
    }
    //注册事件,触发即调用
    this.on(name,func)
  }

}

该实现中用到的一些方法函数

slice

它返回的是一个新的数组对象,通过参数begin和end决定的对原数组的浅拷贝;

!!slice不会影响原数组!!

语法

arr.slice(begin,end)

begin(可选):起始索引值,从0开始;如果它为负数,则从倒是第几个元素开始,-1为倒数第一个;如果begin超过数组长度,则返回空数组;

end(可选):基本与begin相同;如果end不设定,则提到到结尾;如果end超过数组长度,同样提取到结尾;

返回值

返回一个新数组内含被提取元素

splice

通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。

!!splice方法会改变原数组!!

语法

arr.splice(start,deleteCount,item...)

start:起始位置(索引值),与slice的begin相同;

deleteCount(可选):整数,表示要删除的数组元素个数;

item...:添加仅数组的元素,从start开始

返回值

返回一个由被删除的元素组成的数组,没有删除元素则返回空数组;

findIndex()

返回数组中满足提供条件的第一个元素的索引;若没有找到则返回-1;