JavaScript发布订阅模式

257 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第7天,点击查看活动详情

JS中发布订阅模式

发布订阅模式。是一对多的关系,当对象发生改变时,依赖于他的对象都将会得到通知。 在生活中发布订阅模式也是非常常见的场景,比如微信公众号推送。简单来说就是提前预定一件事情,当时机成熟后就会通知订阅者。

我们现在来手写一个发布订阅一对多。

class Event{
  callbacktobj={}//事件回调存储对象
  eventobj = {}//消息历史存储
  //订阅方法
  on(eventname,callback,config){
    if(!this.callbacktobj[eventname){//如果事件尚未发布则创建事件的队列
      this.callbacktobj[eventname] = []
    }
    this.callbacktobj[eventname].push(callback)//把回填存进事件队列中
    // console.log(this.eventobj[eventname],'2');
    if(config&&config.getall&&this.eventobj[eventname]){//如果携带第三个参数,需要获取以前全部的推送信息
      // console.log(this.eventobj[eventname].length-1);
      for(let i = this.eventobj[eventname].length-1 ;i>=0;i--){
        // console.log(123);
        // this.eventobj[eventname][i]//就是事件发布时存储的信息
        callback(this.eventobj[eventname][i])//把以前的事件拿出来都推送一次
      }
    }
  }
  //发布方法
  emit(eventname,msg){
    if(!this.eventobj[eventname]){
      this.callbacktobj[eventname] = []
    }
    this.callbacktobj[eventname].forEach(item => {item(msg)});//首先把最新的信息推送至订阅者
    //然后存储在事件历史中
    if(!this.eventobj[eventname]){
      this.eventobj[eventname] = []
    }
    this.eventobj[eventname].push(msg)
  }
  //取消订阅
  remove(eventname,callback){//传入函数体
    this.callbacktobj[eventname] = this.callbacktobj[eventname].filter(item => item!==callback)
    return 'remove ok'
  }
}

测试运行

const publish = new Event()
//第一次发布
publish.emit('abc',1)
//订阅的回调
const user1 = (msg)=>{console.log(`use1获取信息${msg}`);}
//订阅
publish.on('abc',user1,{getall:true})//第三个参数可以获取以前发布的消息
//第二次发布
publish.emit('abc',2)
//取消订阅
publish.remove('abc',user1)
//第三次订阅
publish.emit('abc',3)

在使用on订阅事件时可传递三个参数第一个是订阅的时间名,第二个是事件发布后需要执行的回调函数,第三个是配置项{getall:true}可以把本次订阅前的发布信息获取到。

使用emit发布函数时可以传递两个参数一个是传递的事件名,第二个是需要传递给订阅者的信息。发布后会调用掉存在回调队列里的函数。并把发布信息存至消息历史队列中。

使用remove取消订阅,传递两个参数传递事件名和回调函数。在回调队列中找到这个回调后删除。

这是自己手写的一个简易版的发布订阅效果,有需要改进的地方大家多多评论