什么是发布订阅
消息的发送者(称为发布者)不会将消息直接发送给特定的接收者(称为订阅者)。而是将发布的消息分为不同的类别,无需了解哪些订阅者可能存在。同样的,订阅者可以表达对一个或多个类别的兴趣,只接收感兴趣的消息,无需了解哪些发布者存在。
实现思路
- 定义一个发布者对象,它有一个缓存列表,用于存放订阅者对象的回调函数
- 定义一个订阅方法,用于向缓存列表中添加回调函数
- 定义一个取消订阅方法,用于从缓存列表中移除回调函数
- 定义一个发布方法,用于遍历缓存列表,依次执行回调函数,并传递相关参数
代码编写
// 发布者对象类型,需要有一个发布方法emit、一个订阅方法on及一个取消订阅的方法remove
type eventClass = {
emit: (name: string) => void
on: (name: string, callback: Function) => void
remove: (name: string, callback: Function) => void
}
// 支持自定义发布事件名称的类型
type ParamsKey = string | number | symbol
// 定义缓存列表的类型---事件名称:事件函数
type eventList = {
[key: ParamsKey]:Array<Function>
}
// 具体实现
class Event implements eventClass{
eventList:eventList
constructor() {
this.eventList = {}
}
// 发布方法
emit(name:string, ...args:Array<any>) {
// 获取对应消息类型的事件数组
let events:Array<Function> = this.eventList[name]
// 遍历事件数组并执行回调函数
events.forEach(item => {
item.apply(this, args)
})
}
// 订阅方法
on(name:string, callback:Function) {
// 如果没有该消息的缓存列表,就创建一个空数组
let fn:Array<Function> = this.eventList[name] || []
fn.push(callback)
this.eventList[name] = fn
}
// 移除方法
remove(key:string, callback:Function) {
// 如果有该消息的缓存列表
if(this.eventList[key]) {
// 遍历缓存列表
for(let i = 0; i <= this.eventList[key].length - 1; i++) {
// 如果存在该事件函数,就从缓存列表中删除
if(this.eventList[key][i] === callback) {
this.eventList[key].splice(i, 1)
}
}
}
}
}
export default new Event()