前言
谈到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
网友评论