发布订阅
js
class EventEmitter {
// 使用Map对象来存储事件及其对应的监听器函数
events = new Map();
/**
* 绑定事件到指定监听器函数。
* 如果监听器不是一个函数,则抛出类型错误。
* @param {string} event - 事件名称。
* @param {Function} listener - 监听器函数。
*/
on(event, listener) {
if (typeof listener !== 'function') {
throw new TypeError('Listener must be a function.');
}
if (!this.events.has(event)) {
this.events.set(event, new Set());
}
this.events.get(event).add(listener);
}
/**
* 移除指定事件的指定监听器函数。
* 如果事件不存在,则发出警告。
* @param {string} event - 事件名称。
* @param {Function} listener - 要移除的监听器函数。
*/
off(event, listener) {
if (!this.events.has(event)) {
console.warn(`Event "${event}" does not exist.`);
return;
}
const listeners = this.events.get(event);
listeners.delete(listener);
if (listeners.size === 0) {
this.events.delete(event);
}
}
/**
* 移除所有事件的所有监听器。
*/
offAll() {
this.events.clear();
}
/**
* 触发指定事件,并将参数传递给监听器函数。
* 如果没有监听器被调用,则返回false。
* 当调用监听器函数时,使用try-catch来防止错误影响其他监听器。
* @param {string} event - 事件名称。
* @param {*} args - 传递给监听器函数的参数列表。
* @return {boolean} 事件是否被触发。
*/
emit(event, ...args) {
if (!this.events.has(event)) {
return false;
}
const listeners = this.events.get(event);
for (const listener of listeners) {
try {
listener(...args);
} catch (error) {
console.error(`Error occurred when executing listener for event "${event}":`, error);
}
}
return true;
}
/**
* 绑定事件到一个只会被触发一次的监听器。
* 监听器触发一次后会自动被移除。
* @param {string} event - 事件名称。
* @param {Function} listener - 监听器函数。
*/
once(event, listener) {
// 一次性包装函数
const onceWrapper = (...args) => {
listener(...args); // 调用原始监听器
this.off(event, onceWrapper); // 移除包装函数
};
this.on(event, onceWrapper); // 绑定包装函数作为监听器
}
}
export default new EventEmitter();使用示例
javascript
// 订阅
Event.on("test-method", val => {
// ...
})
// 发布
Event.emit("test-method", false)