描述
一个对象的某个状态改变时,订阅了这个对象的其他对象都将收到改对象状态改变的通知。
角色:发布者、订阅者、调度中心(处理中心)
- 发布者(publisher),发布事件到订阅中心,使得调度中心通知订阅了该对象的所有订阅者(subscriber);
- 订阅者(subscriber),把自己关注的发布者注册到调度中心,使得订阅的发布者发布事件是,调度中心能够通知到自己
- 调度中心,统一管理发布者订阅者之间的关系,当发布者发布事件时,通知订阅此发布者消息的所有订阅者;实现发布者订阅者之间的解耦。
JavaScript实现发布订阅模式
class Event {
constructor () {}
// 调度中心:首先定义一个事件容器,用来装事件数组(因为订阅者可以是多个)
handlers = {};
// 订阅者向调度中心订阅方法:
addEventListener(type:any, handler:any) {
// 首先判断handlers内有没有type事件容器,没有则创建一个新数组容器
if (!(type in this.handlers)) {
this.handlers[type] = []
}
// 将事件存入
this.handlers[type].push(handler)
}
//修改调度中心中发布者下订阅者列表为指定的单个
changeSingleEventListener(type:any, handler:any){
if (!(type in this.handlers)) {
this.handlers[type] = []
}
this.handlers[type]= [handler];
}
// 发布者向调度中心发布消息:触发事件两个参数(事件名,参数)
// @ts-ignore
dispatchEvent(type:any, ...params:any[]) {
// 若没有注册该事件则抛出错误
if (!(type in this.handlers)) {
return new Error('未注册该事件')
}
// 便利触发
this.handlers[type].forEach((handler:any) => {
handler(...params)
})
}
// 向调度中心移除订阅者方法:事件移除参数(事件名,删除的事件,若无第二个参数则删除该事件的订阅和发布)
// @ts-ignore
removeEventListener(type:any, handler:any) {
// 无效事件抛出
if (!(type in this.handlers)) {
return new Error('无效事件')
}
if (!handler) {
// 直接移除事件
delete this.handlers[type]
} else {
const idx = this.handlers[type].findIndex((ele:any) => ele === handler);
// 抛出异常事件
if (idx === undefined) {
return new Error('无该绑定事件')
}
// 移除事件
this.handlers[type].splice(idx, 1)
if (this.handlers[type].length === 0) {
delete this.handlers[type]
}
}
}
}
// @ts-ignore
// js引入及创建调度中心对象
let event = new Event();
向外抛出调度对象中处理发布者、订阅者之间的方法
export const addEventListener = (type: any, handler: any) => event.addEventListener(type, handler);
export const changeSingleEventListener = (type: any, handler: any) => event.changeSingleEventListener(type, handler);
export const removeEventListener = (type:any, handler:any) => event.removeEventListener(type, handler);
export const dispatchEvent = (type:any, ...params:any) => event.dispatchEvent(type, ...params);
简易版本:
调度中心
let callbacks = new Map();
const on = (topic, callback) => {
if (typeof callback !== 'function') return;
callbacks.set(topic, callback)
};
const off = topic=> {
callbacks.has(topic) && callbacks.delete(topic);
};
const emit = (topic, data) => {
if (callbacks.has(topic)) {
const callback = callbacks.get(topic);
typeof callback === 'function'&&callback(data);
}
};
module.exports = {
on:on,
off:off,
emit:emit
};
订阅者使用
const subscription = require("subscription.js");
subscription.on("topic name",()=>{})
发布者使用
const subscription = require("subscription.js");
subscription.emit("topic name",{})
评论区