[JS] 事件总线

这篇具有很好参考价值的文章主要介绍了[JS] 事件总线。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

事件总线与发布订阅模式

事件总线是对发布-订阅模式的一种实现。

发布-订阅模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。

发布-订阅模式实现了松耦合,发布者不是直接将消息发送给订阅者,而是经过了一个中间的代理,事件总线就是一种中间代理的实现。

事件总线维护了一个事件列表,订阅者可以订阅某一个事件,并指定一个回调(回调的具体实现在订阅者内部);

每个事件又维护了一个依赖列表,发布者可以“触发”一个事件,事件总线负责遍历该事件的依赖列表,调用每一个当初订阅者订阅时指定的回调函数。

在 JS 中实现Event Bus

定义一个EventBus类:

class EventBus{}

需要维护一个事件列表,在初始化事件总线对象的时候创建。

对于每一个事件,我们需要记录它的事件名(string类型),还需要记录该事件的依赖列表(Array<Function>类型),依赖列表其实就是各个订阅者的回调函数的列表。

这采用了一个对象来记录多个事件,刚好键值对就是事件名:依赖列表

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:回调函数文章来源地址https://www.toymoban.com/news/detail-747090.html

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];
}

到了这里,关于[JS] 事件总线的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • js 中单例模式、工厂模式、装饰模式、发布订阅模式、适配器模式、

    简单概述:将每个功能拆分到最小化,最后将小功能拼接到一起

    2024年02月11日
    浏览(33)
  • WPF 如何设置全局的订阅发布事件

    我们需要一个全局事件订阅发布功能,实现页面通讯。使两个毫无关系的页面通过一个中间量进行通讯。 IEventAggregator:消息订阅集合 这个是Prism提供的消息订阅功能。使用如下 设置订阅类型,即 官方案例,在ViewModel中使用 Tips:订阅中传递的值和EventClass: PubSubEventstr

    2024年02月15日
    浏览(30)
  • [JS] 事件总线

    事件总线是对发布-订阅模式的一种实现。 发布-订阅模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。 发布-订阅模式实现了松耦合,发布者不是直接将消息发送给订阅者,而是经过了一个中间的代理,事件总线就

    2024年02月05日
    浏览(23)
  • 设计模式 ~ 发布订阅模式

    用于实现对象之间的松耦合通信; 在该模式中,存在一个或多个发布者(Publishers)和一个或多个订阅者(Subscribers); 发布者负责发布消息,而订阅者负责订阅感兴趣的消息并在接收到消息时做出相应的处理。 Subject 和 Observer 直接绑定,中间无媒介; Publisher 和 Observer 相互

    2024年02月16日
    浏览(27)
  • 设计模式之订阅发布模式

    订阅发布模式(Publish-Subscribe Pattern)是一种行之有效的解耦框架与业务逻辑的方式,也是一种常见的观察者设计模式,它被广泛应用于事件驱动架构中。 在这个模式中,发布者(或者说是主题)并不直接发送消息给订阅者,而是通过调度中心(或者叫消息代理)来传递消息

    2024年02月06日
    浏览(28)
  • Spring Boot - Application Events 同步 VS 异步 发布订阅事件实战

    Spring Boot - Application Events 的发布顺序_ApplicationStartingEvent Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent Spring Boot - Application Events 的发布顺序_ApplicationContextInitializedEvent Spring Boot - Application Events 的发布顺序_ApplicationPreparedEvent Spring Boot - Application Events 的发布顺

    2024年01月17日
    浏览(47)
  • 观察者模式和发布订阅模式

    观察者模式与发布订阅模式的区别: 1、观察者模式中只有观察者和被观察者,发布订阅模式中有发布者、订阅者、调度中心 2、观察者模式是被观察者发生变化时自己通知观察者,发布订阅模式是通过调度中心来进行分布订阅操作 vue2中响应式数据就是由Object.defineProperty()和

    2024年02月13日
    浏览(32)
  • 行为型:发布订阅模式

      发布订阅模式是基于一个事件(主题)通道,希望接收通知的对象 Subscriber (订阅者) 通过自定义事件订阅主题,被激活事件的对象 Publisher (发布者) 通过发布主题事件的方式通知订阅者 Subscriber (订阅者) 对象。   简单说就是 发布者与订阅者通过事件来通信 ,

    2023年04月11日
    浏览(28)
  • 观察者模式, 发布-订阅模式, 监听器模式

    观察者模式是一种 行为型 设计模式, 定义对象间的一种 一对多 的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新 角色模型和结构图 在观察者模式中,只有两种主体:目标对象 ( Object ) 和 观察者 ( Observer )。宗门任务大殿就是目标对象

    2024年02月22日
    浏览(30)
  • 观察者模式和发布订阅模式的区别

    从下图中可以看出, 观察者模式中观察者和目标直接进行交互,而发布订阅模式中统一由调度中心进行处理,订阅者和发布者互不干扰 。这样一方面实现了 解耦 ,还有就是可以实现更细粒度的一些控制。比如发布者发布了很多消息,但是不想所有的订阅者都接收到,就可以

    2024年02月22日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包