1. 前言
订阅/发布模式是常用的设计模式,也可以称为观察者模式。在NodeJS和前端开发中,也有很多地方有涉及,NodeJS原生自带EventEmitter、Redux等等。在实际SPA项目中,不同模块之间会需要这种设计,比如:A模块生成一条待执行命令,并不立即执行,需要B模块执行某些动作或满足某些条件,再触发执行这一条待执行命令。
本文借鉴NodeJS的EventEmitter,基于ES6的Map和Set,自己实现一个EventEmitter,满足基本的发布/订阅功能。
2. 实现说明
实现常用功能:
on
: 订阅一条事件,使用Set收纳事件,使用Map区分事件名称;once:
订阅一条一次性的事件;emit
: 发布事件,对由once方法订阅的事件,执行一次即清除;off
: 取消订阅,可以取消指定事件名称所有订阅,也可以取消指定事件名称和事件内容的订阅;- clear: 清理全部未发布的事件。
3. 完整源码
class EventEmitter {
events = new Map();
constructor() {}
getEvents(eventName) {
if(eventName) {
let list = this.events.get(eventName);
if(!list) {
this.events.set(eventName, new Set());
list = this.events.get(eventName);
}
return list;
} else {
return this.events;
}
}
on(eventName, executor) {
const list = this.getEvents(eventName);
list.add(executor);
return () => {
list.delete(executor);
}
}
once(eventname, executor) {
executor.once = true;
return this.on(eventname, executor);
}
emit(eventName) {
let list = this.events.get(eventName);
if(list) {
for(const handler of list) {
try {
handler();
} catch(e) {
console.log(e);
}
if(handler.once) {
list.delete(handler);
}
}
}
}
off(eventName, executor) {
let list = this.events.get(eventName);
if(list) {
if(executor) {
list.delete(executor);
} else {
list.clear();
}
}
}
clear() {
this.events.clear();
}
}
注:以上,如有不合理之处,还请帮忙指出,大家一起交流学习~