当前位置: 首页 > news >正文

JS订阅发布模式

什么是发布订阅模式

发布-订阅模式又叫做观察者模式。他定义了一种一对多的依赖关系,即当一个对象的状态发生变化的时候,所有依赖的对象都会得到通知。

基本实现

把自己想象成公司的秘书,领导需要开一个会议,需要你去通知所有参会人员;

这里有几个元素:

  • 发布者(秘书)
  • 与会人员(需要参加会议的人员)

还有几个方法:

  • 制作与会人员名单
  • 删除不参加的人
  • 发送会议通知,以及必要的时间地点等信息

你首先需要把所有的与会人员名单收集起来(也就是添加依赖函数),然后根据清单发送通知,并携带必要的会议信息,与会人员收到信息后会做出相应的反应(回调函数中的处理逻辑)

let yourMsg = {};
yourMsg.peopleList = [];
yourMsg.listen = function (fn) {
    this.peopleList.push(fn);
}
yourMsg.triger = function () {
  let that = this
  let args = arguments
  setTimeout(function() {
    for(let i = 0,fn;fn=that.peopleList[i++];){
        fn.apply(that,args);
    }
  },2000)
    
}

yourMsg.listen(function () {
    console.log('我被通知了,我回去参加会议,给我时间地点')
    console.log(`title:${arguments[0]}`);
    console.log(`time:${arguments[1]}`);
})
yourMsg.listen(function () {
  console.log('我被通知了,但是我不care')
})
yourMsg.listen(function () {
  console.log('我被通知了,Jack代替我去')
})

yourMsg.triger('会议', '3:00');

复制代码

这便是一个简单的订阅发布模式

分主题的订阅发布模式

随着公司业务量的增加,你的会议不需要所有人都参加,你需要分主题维护一份参会人员名单;

比如,产品会议需要小A,小B参加;而技术会议需要小C,小D参加;

这里我们通过在添加与会人员的时候添加一个‘key’值代表该成员需要参加的会议类型;

let yourMsg = {};
yourMsg.peopleList = [];
yourMsg.listen = function (key, fn) {
  if (!this.peopleList[key]) {
    this.peopleList[key] = [] // 如果分类中没有此类型的消息,则新建一个
  }
  this.peopleList[key].push(fn);
}
yourMsg.triger = function () {
  let key = Array.prototype.shift.call(arguments)
  let fns = this.peopleList[key]
  let that = this
  let args = arguments
  if (!fns) {
    return false
  }
  setTimeout(function() {
    for(let i = 0,fn;fn=fns[i++];){
        fn.apply(that,args);
    }
  }, 200)
    
}

yourMsg.listen('prod', function () {
    console.log('小A: 我只关心会议消息,其它的事别来烦我')
    console.log(`title:${arguments[0]}`);
    console.log(`time:${arguments[1]}`);
})
yourMsg.listen('prod', function () {
    console.log('小B: 会议使我精神百倍!')
    console.log(`title:${arguments[0]}`);
    console.log(`time:${arguments[1]}`);
})
yourMsg.listen('tech', function () {
  console.log('小C:我只关心技术会议,产品会议让那些傻瓜去吧')
})
yourMsg.listen('tech', function () {
  console.log('小D:又到技术会议时间了?我是被逼的!')
})

yourMsg.triger('prod', '开会啦', '下午3:00');
yourMsg.triger('tech');
复制代码

可以随处调用的订阅发布功能

由于你们公司效益特别好,你一个秘书已经忙不过来,这个时候,公司又来了一位秘书。你只需要把你通知会议安排的方法告诉他,让他按照这个模式去做就好了。

这里我们并没有用对象来做,而是通过Object.Create()通过依赖关系来实现类似继承的效果;更加的合理简洁;个人我认为在js中完全没必要也不应该使用面向对象的模式,因为它压根就么有所谓的面向对象,相比于东施效颦不如发挥自己的特点。

let installer = {
  peopleList: [],
  listen (key, fn) {
    if (!this.peopleList[key]) {
      this.peopleList[key] = [] // 如果分类中没有此类型的消息,则新建一个
    }
    this.peopleList[key].push(fn);
  },
  triger () {
    let key = Array.prototype.shift.call(arguments)
    let fns = this.peopleList[key]
    let that = this
    let args = arguments
    if (!fns) {
      return false
    }
    setTimeout(function() {
      for(let i = 0,fn;fn=fns[i++];){
          fn.apply(that,args);
      }
    }, 200)
      
  },
  remove (key, fn) {
    let fns = this.peopleList[key]
    if (!fns) {
      return false
    }

    for (let index = 0; index < fns.length; index++) {
      const _fn = fns[index];
      if(_fn === fn){
          fns.splice(index,1);
      }
    }
  }
}

let yourMsg = Object.create(installer);

yourMsg.listen('prod', function () {
    console.log('小A: 我只关心会议消息,其它的事别来烦我')
    console.log(`title:${arguments[0]}`);
    console.log(`time:${arguments[1]}`);
})
yourMsg.listen('prod', function () {
    console.log('小B: 会议使我精神百倍!')
    console.log(`title:${arguments[0]}`);
    console.log(`time:${arguments[1]}`);
})


let smA = function () {
  console.log('小C:我只关心技术会议,产品开会让那些傻瓜去吧')
}
let smB = function () {
  console.log('小D:又到技术会议时间了?我是被逼的!')
}
yourMsg.listen('tech', smA)
yourMsg.listen('tech', smB)

yourMsg.remove('tech', smA)

yourMsg.triger('prod', '开会啦', '下午3:00');
yourMsg.triger('tech', smA);
复制代码

转载于:https://juejin.im/post/5c063537e51d451dbc218043

相关文章:

  • 《Web全栈工程师的自我修养》读书笔记
  • 五、自定义转化器,视图层之httprequest对像、HttpResponse、JsonRepons
  • $(selector).each()和$.each()的区别
  • CSS盒模型的介绍
  • Docker 入门
  • 安装Kubernetes的坑 ---- Flanneld
  • 简单类型和对象的区别
  • Java基础之关键字
  • 作用域和名称空间
  • 云主机文件系统readonly处理案例
  • STM8S003F3通过PWM波实现三基色呼吸灯(转)
  • 前端技术周刊 2018-12-10:前端自动化测试
  • puppet连载22:define用法
  • Django2.0——请求与响应(下)
  • 华为敏捷DevOps实践:如何从Excel管理软件的方式中走出来
  • __proto__ 和 prototype的关系
  • 【知识碎片】第三方登录弹窗效果
  • angular组件开发
  • Docker 笔记(1):介绍、镜像、容器及其基本操作
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • Mithril.js 入门介绍
  • node入门
  • Python连接Oracle
  • uni-app项目数字滚动
  • 闭包,sync使用细节
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 发布国内首个无服务器容器服务,运维效率从未如此高效
  • 聊聊flink的BlobWriter
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 漂亮刷新控件-iOS
  • 删除表内多余的重复数据
  • 设计模式走一遍---观察者模式
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用SAX解析XML
  • 学习笔记:对象,原型和继承(1)
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 云大使推广中的常见热门问题
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • (1综述)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练
  • (22)C#传智:复习,多态虚方法抽象类接口,静态类,String与StringBuilder,集合泛型List与Dictionary,文件类,结构与类的区别
  • (独孤九剑)--文件系统
  • (附源码)spring boot校园拼车微信小程序 毕业设计 091617
  • (附源码)springboot 个人网页的网站 毕业设计031623
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (实战篇)如何缓存数据
  • (五)关系数据库标准语言SQL
  • (学习日记)2024.01.19
  • (一)SpringBoot3---尚硅谷总结
  • .netcore 获取appsettings
  • .Net各种迷惑命名解释
  • .net与java建立WebService再互相调用
  • [Asp.net MVC]Bundle合并,压缩js、css文件