定义
发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。 订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
实现思路
- 创建一个
EventHub类 - 在该类上创建一个事件中心(Map)
on方法用来把函数 fn 都加到事件中心中(订阅者注册事件到调度中心)emit方法取到 arguments 里第一个当做 event,根据 event 值去执行对应事件中心中的函数(发布者发布事件到调度中心,调度中心处理代码)off方法可以根据 event 值取消订阅(取消订阅)once方法只监听一次,调用完毕后删除缓存函数(订阅一次)- 注册一个
newListener用于监听新的事件订阅 完整代码:
class EventHub{
map(){
this._events = {};
}
on(eventName, callback){
if(this._events[eventName]){
if(this.eventName !== "newListener"){
this.emit("newListener", eventName)
}
}
const callbacks = this._events[eventName] || [];
callbacks.push(callback);
this._events[eventName] = callbacks
}
emit(eventName, ...args){
const callbacks = this._events[eventName] || [];
callbacks.forEach(cb => cb(...args))
}
once(eventName, callback){
const one = (...args)=>{
callback(...args)
this.off(eventName, one)
}
one.initialCallback = callback;
this.on(eventName, one)
}
off(eventName, callback){
const callbacks = this._events[eventName] || []
const newCallbacks = callbacks.filter(fn => fn != callback && fn.initialCallback != callback /* 用于once的取消订阅 */)
this._events[eventName] = newCallbacks;
}
}
// test
const events = new EventHub()
events.on("newListener", function(eventName){
console.log(`eventName`, eventName)
})
events.on("hello", function(){
console.log("hello");
})
let cb = function(){
console.log('cb');
}
events.on("hello", cb)
events.off("hello", cb)
function once(){
console.log("once");
}
events.once("hello", once)
events.off("hello", once)
events.emit("hello")
events.emit("hello")