实现一个简单的EventHub

作者: 大春春 | 来源:发表于2019-08-21 20:54 被阅读64次

    前言

    谈到EventHub就不得不说到发布订阅这一种设计模式,EventHub正是基于这种设计模式实现出来的一个实例,当前在前端方面,EventHub应用已经十分广泛了,例如Vue中的eventbus、redux也对EventHub有所借鉴(redux是单向数据流,遵循MVC结构,M的数据更新后V紧接着更新界面,而EventHub的数据流是没有方向限制的)

    什么是EventHub

    前言谈到EventHub是基于发布订阅模式实现的一个实例,那么要搞清楚EventHub就先要搞清楚什么是发布订阅模式。

    • 什么是发布订阅模式
      因为发布订阅模式是一个抽象的东西,所以在此我只能以一个例子来做比喻:
      假设你是一个赏金猎人,通过接取各式各样的任务来赚取赏金,但同时你又不认识发布任务的人,而发布任务的人也不知道你这个人的存在,这时候就需要一个工会,工会负责接受委托人发布任务,与此同时也能向赏金猎人提供任务,关系大致如下:


      image.png

      这就相当于委托人发布任务,赏金猎人订阅任务并执行。

    • EventHub是什么,有什么用?
      基于上面的发布订阅模式,我们把赏金猎人设定为模块A,而委托人设定为模块B,那么这个任务中心就是EventHub了,也就是说是一个事件委托中心。
      以此也就不难知道,EventHub就是用来多模块间进行通信的工具,最典型的例子就是Vue中的eventbus。


      image.png

    实现一个简单的EventHub

    从上面所说的可以得知,EventHub的实现其实就几个功能,发布(on),订阅(emit),当然还有可能存在取消任务的情况(off),这样就足够实现一个简单的EventHub了,不废话,代码如下:

    type Event = (data?: any) => any
    
    class EventHub {
        // cache用于存储事件,存储中心
        cache: { [key: string]: Event[] } = {}
    
        // 接收事件名和事件,同时将其放入到存储中心
        on = (name: string, fn: Event) => {
            this.cache[name] = this.cache[name] || []
            this.cache[name].push(fn)
        }
    
        // 被订阅的时候,将存储中心对应事件名的所有事件拿出来执行
        emit = (name: string, data?: any) => {
            if(this.cache[name] === undefined) return
            this.cache[name].forEach(fn => {
                fn(data)
            })
        }
    
        // 取消事件的时候,将被取消的事件从对应事件名中剔除
        off = (name: string, fn: Event) => {
            if(this.cache[name] === undefined) return
            this.cache[name] = this.cache[name].filter(f => f !== fn)
        }
    }
    

    接着我们来看看效果:
    订阅成功:


    image.png

    取消订阅:


    image.png

    相关文章

      网友评论

        本文标题:实现一个简单的EventHub

        本文链接:https://www.haomeiwen.com/subject/bqvisctx.html