注册
|
登录
发帖
热搜
活动
交友
discuz
论坛
BBS
翼度工具
翼度网址导航
开发工具
Linux命令速查
网页设计配色表
在线制作icon
颜色代码选取器
翼度科技
»
论坛
›
编程开发
›
JavaScript
›
查看内容
返回列表
发新帖
[JS] 事件总线
亚囡
亚囡
当前离线
积分
30
10
主题
10
帖子
30
积分
新手上路
新手上路, 积分 30, 距离下一级还需 20 积分
新手上路, 积分 30, 距离下一级还需 20 积分
积分
30
发消息
显示全部楼层
事件总线与发布订阅模式
事件总线是对发布-订阅模式的一种实现。
发布-订阅模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。
发布-订阅模式实现了松耦合,发布者不是直接将消息发送给订阅者,而是经过了一个中间的代理,事件总线就是一种中间代理的实现。
事件总线维护了一个事件列表,订阅者可以订阅某一个事件,并指定一个回调(回调的具体实现在订阅者内部);
每个事件又维护了一个依赖列表,发布者可以“触发”一个事件,事件总线负责遍历该事件的依赖列表,调用每一个当初订阅者订阅时指定的回调函数。
在 JS 中实现Event Bus
定义一个EventBus类:
class EventBus{}
复制代码
需要维护一个事件列表,在初始化事件总线对象的时候创建。
对于每一个事件,我们需要记录它的事件名(string类型),还需要记录该事件的依赖列表(Array类型),依赖列表其实就是各个订阅者的回调函数的列表。
这采用了一个对象来记录多个事件,刚好键值对就是事件名:依赖列表
constructor(){
this.eventObject = {};
}
复制代码
实现订阅
:
每一次订阅需要指定
订阅的事件名
和
发布时要触发的回调函数
。
如果指定的事件不存在,则添加一个事件,并推入该新依赖(回调函数)。
如果指定的事件存在,则直接推入新依赖(回调函数)
subscribe(eventName, callback){
if(!this.eventObject[eventName]){
this.eventObject[eventName] = [];
}
this.eventObject[eventName].push(callback);
}
复制代码
实现发布
:
发布也要考虑到指定的事件是否存在。如果不存在,则中断并返回警告;如果存在指定事件,则依次调用事件的依赖列表(回调列表)。
publish(eventName){
const callbackList = this.eventObject[eventName];
if(!callbackList)return console.warn(eventName + " Not Found!");
for(let callback of callbackList){
callback();
}
}
复制代码
汇总如下
:
class EventBus{
constructor(){
this.eventObject = {};
}
/**
* @param {string} eventName
*/
publish(eventName){
const callbackList = this.eventObject[eventName];
if(!callbackList)return console.warn(eventName + " Not Found!");
for(let callback of callbackList){
callback();
}
}
/**
* @param {string} eventName
* @param {Function} callback
*/
subscribe(eventName, callback){
if(!this.eventObject[eventName]){
this.eventObject[eventName] = [];
}
this.eventObject[eventName].push(callback);
}
}
复制代码
优化Event Bus的实现
在发布时传递参数
使用...args介绍不定长参数列表,在发布时传入,并在调用回调函数列表的时候依次传入。
/**
* @param {string} eventName
*/
publish(eventName, ...args){
const callbackList = this.eventObject[eventName];
if(!callbackList)return console.warn(eventName + " Not Found!");
for(let callback of callbackList){
callback(...args);
}
}
复制代码
提供取消订阅的操作
在订阅者调用subscribe方法订阅事件的时候,返回一个用于取消订阅的unSubscribe方法。
在实现事件的回调函数列表的时候,需要为每一个回调函数添加一个id,方便以后查询并删除该回调函数。
这里将订阅的回调函数列表换成用对象结构存储,因为在数组中删除某个中间元素较麻烦且耗时,效率不如对象结构的delete删除键值对。
换成对象结构存储后,键值对表示:id:回调函数。
class EventBus{
constructor(){
// 初始化事件列表
this.eventObject = {};
// 回调函数列表的 id
this.callbackId = 0;
}
/**
* @param {string} eventName
*/
publish(eventName, ...args){
// 取出该事件的回调函数列表(对象)
const callbackObject = this.eventObject[eventName];
if(!callbackObject)return console.warn(eventName + " Not Found!");
// 执行每一个回调函数,这里的id是对象的key
for(let id in callbackObject){
callbackObject[id](...args);
}
}
/**
* @param {string} eventName
* @param {Function} callback
* @returns {{
* unSubscribe: Function
* }}
*/
subscribe(eventName, callback){
if(!this.eventObject[eventName]){
this.eventObject[eventName] = {};
}
// 为当前事务的回调函数申请一个专属id
const id = this.callbackId++;
// 绑定回调函数
this.eventObject[eventName][id] = callback;
// 生成取消订阅的函数
const unSubscribe = ()=>{
// 删除该回调函数
delete this.eventObject[eventName][id];
// 如果该事件的回调函数都删完了,则顺便删除事件列表中的事件
if(Object.keys(this.eventObject[eventName]).length === 0){
delete this.eventObject[eventName];
}
}
return {unSubscribe};
}
}
复制代码
清除某个事件
/**
* @description 清除某事件
* @param {string} eventName
*/
clear(eventName){
if(!this.eventObject.hasOwnProperty(eventName)){
return console.warn(eventName + " Not Found!");
}
delete this.eventObject[eventName];
}
复制代码
来源:
https://www.cnblogs.com/feixianxing/p/js-event-bus-publish-subscribe-pattern.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
上一篇:
Promise规范与原理解析
下一篇:
webpack4.0+简要
发表于 2023-11-25 16:16:16
举报
回复
使用道具
分享
返回列表
发新帖
本版积分规则
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
快速回复
快速回复
返回顶部
返回顶部
返回列表
返回列表