请手写一个发布-订阅的模式

news/2024/10/23 20:31:08/

发布-订阅模式也是经典的设计模式之一,它在前端很多地方都有应用,比如javascript事件池Vue的$on、$offnodejs的events模块和socket通信等等都有应用,也是前端面试比较火热的考点之一,接下来给大家详细介绍下发布-订阅模式

发布-订阅模式定义了对象间的一种一对多的依赖关系当一个对象的状态发生变化时,所有依赖它的对象都将得到通知。在JavaScript开发中,我们一般用事件模型来替代传统的发布-订阅模式

要手写一个简单的发布订阅模式,其实现思路如下:

  1. 先初始化一个events对象
  2. 调用on方法时,将事件名称eventName和监听函数fn存入events对象
  3. 调用emit方法时,通过事件名称eventNameevents对象中取出对应的回调并执行
  4. off方法:通过事件名称eventName找出events对象对应的监听函数并清除
  5. once方法:被emit触发一次后就立即调用off方法移除监听,也就是调用once传入的监听函数只会执行一次

代码不多,所以直接上完整代码

class EventEmitter {constructor() {this.events = {}}on(eventName, fn) {if (!this.events[eventName]) {this.events[eventName] = []}this.events[eventName].push(fn)console.log(this,'this')return this}once(eventName, fn) {const func = (...args) => {this.off(eventName, func)fn.apply(this, args)}this.on(eventName, func)return this}emit(eventName, ...args) {if (!this.events[eventName]) return thisthis.events[eventName].forEach(fn => {fn.apply(this, args)});return this}off(eventName, fn) {if (!this.events[eventName]) return thisif (typeof fn === 'function') {this.events[eventName] = this.events[eventName].filter((f) => f !== fn)return this}this.events[eventName] = nullreturn this}
}

const events = new EventEmitter();events.on('event1', () => {console.log('event1', '第一个监听函数')
})
events.on('event1', () => {console.log('event1', '第二个监听函数')
})
events.emit('event1')const fn1 = () => {console.log('event2', '第一个监听函数')
}
const fn2 = () => {console.log('event2', '第二个监听函数')
}
events.on('event2', fn1)
events.on('event2', fn2)
events.off('event2', fn1);// 打印结果:
// event1 第一个监听函数
// event1 第二个监听函数// 上面代码有疑问请阅读下面代码,这部分解答了上面读者的疑问
const events = new EventEmitter();// event1部分
events.on('event1', () => {console.log('event1', '第一个监听函数')
})
events.on('event1', () => {console.log('event1', '第二个监听函数')
})
events.emit('event1')// event2部分
const fn1 = () => {console.log('event2', '第一个监听函数')
}
const fn2 = () => {console.log('event2', '第二个监听函数')
}
events.on('event2', fn1)
events.off('event2', fn1);
events.on('event2', fn2)
events.emit('event2')

  • 可以广泛应用于异步编程中,这是一种替代传递回调函数的方案;
  • 可以取代对象之间硬编码的通知机制,一个对象不用再显示地调用一个对象的接口


http://www.ppmy.cn/news/1239298.html

相关文章

2023人形机器人行业海外科技研究:从谷歌看机器人大模型进展

今天分享的是人形机器人系列深度研究报告:《2023人形机器人行业海外科技研究:从谷歌看机器人大模型进展》。 (报告出品方:华鑫证券) 报告共计:26页 大模型是人形机器人的必备要素 长期来看,人…

3、Qt使用windeploy工具打包可执行文件

新建一个文件夹,把要打包的可执行文件exe拷贝过来 点击输入框,复制一下文件夹路径 点击电脑左下角,找到Qt文件夹, 点击打开 “Qt 5.12.0 for Desktop” (我安装的是Qt 5.12.0版本) 输入“cd bin”&#xff…

Java实现求最大值

1 问题 接收用户输入的3个整数,如何将最大值作为结果输出。 2 方法 采用“截图文字代码”的方式描述。 引入输入包调用main()函数,提示并接收用户输入的3个整数,并交由变量a b c来保存。对接收的3个数据进行比较,先比较a和b&#…

【Essential C++学习笔记】第六章 以Template进行编程

文章目录 第六章 以Template进行编程前言:6.1 被参数化的型别1)为什么要有类模板呢?2)具体实施 6.2 模板类的定义6.3 模板类型参数的处理6.4 实现一个模板类1)实现逻辑1.理清思路2.insert()3.remove()4.remove_root()5.remove_va…

数据结构与算法编程题19

统计二叉树的叶结点个数。 #define _CRT_SECURE_NO_WARNINGS#include <iostream> using namespace std;typedef char ElemType; #define ERROR 0 #define OK 1 typedef struct BiNode {ElemType data;BiNode* lchild, * rchild; }BiNode,*BiTree;bool Create_tree(BiTre…

EXIT外部中断 HAL库+cubeMX

一.cubeMX外部中断配置 1.系统内核 2.中断管理 3.选择抢占优先级和响应优先级&#xff0c;共有5个等级&#xff0c;在这里就使用库函数编写代码时最常用的2位抢占优先级2位响应优先级。 4.勾选使能选项&#xff0c;后面的两个零&#xff0c;第一个代表抢占优先级的等级&#xf…

25 Linux I2C 驱动

一、I2C简介 I2C老朋友了&#xff0c;在单片机里面也学过&#xff0c;现在再复习一下。I2C使用两条线在主控制器和从机之间进行数据通信。一条是 SCL(串行时钟线)&#xff0c;另外一条是 SDA(串行数据线)&#xff0c;这两条数据线需要接上拉电阻&#xff0c;总线空闲的时候 SCL…

【mybatis注解实现条件查询】

文章目录 步骤1: 引入MyBatis依赖步骤2: 创建数据模型步骤3: 创建Mapper接口步骤4: 配置MyBatis步骤5: 执行条件查询 步骤1: 引入MyBatis依赖 <dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.x.…