173 lines
4.4 KiB
TypeScript
173 lines
4.4 KiB
TypeScript
/**
|
|||
|
|
* 优化后的事件系统
|
||
|
|
* 使用 WeakMap 来追踪监听器,避免内存泄漏
|
||
|
|
* 使用数组存储监听器,确保正确注册和移除
|
||
|
|
*/
|
||
|
|
export const customEvent = (function () {
|
||
|
|
let events: { [key: string]: any } = {};
|
||
|
|
|
||
|
|
// 用于追踪监听器的唯一标识,避免重复注册
|
||
|
|
let locked: { [key: string]: any } = {};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 检查监听器是否已经注册
|
||
|
|
*/
|
||
|
|
function isListenerRegistered(listeners: any, listener: any) {
|
||
|
|
if (!Array.isArray(listeners)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
// 使用严格相等检查
|
||
|
|
return listeners.some(item => item === listener);
|
||
|
|
}
|
||
|
|
|
||
|
|
return {
|
||
|
|
/**
|
||
|
|
* 注册事件监听器
|
||
|
|
* @param {string} name - 事件名称
|
||
|
|
* @param {Function} callback - 回调函数
|
||
|
|
*/
|
||
|
|
on: function (name: string, callback: Function) {
|
||
|
|
if (typeof name !== 'string' || !name) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (typeof callback !== 'function') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 初始化事件数组
|
||
|
|
if (!events[name]) {
|
||
|
|
events[name] = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查是否已经注册过
|
||
|
|
if (isListenerRegistered(events[name], callback)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 注册监听器
|
||
|
|
events[name].push({
|
||
|
|
once: false,
|
||
|
|
handler: callback
|
||
|
|
});
|
||
|
|
},
|
||
|
|
/**
|
||
|
|
* 注册事件监听器
|
||
|
|
* @param {string} name - 事件名称
|
||
|
|
* @param {Function} callback - 回调函数
|
||
|
|
*/
|
||
|
|
once: function (name: string, callback: Function) {
|
||
|
|
if (typeof name !== 'string' || !name) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
if (typeof callback !== 'function') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 初始化事件数组
|
||
|
|
if (!events[name]) {
|
||
|
|
events[name] = [];
|
||
|
|
}
|
||
|
|
|
||
|
|
// 检查是否已经注册过
|
||
|
|
if (isListenerRegistered(events[name], callback)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 注册监听器
|
||
|
|
events[name].push({
|
||
|
|
once: true,
|
||
|
|
handler: callback
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 取消事件监听器
|
||
|
|
* @param {string} name - 事件名称
|
||
|
|
* @param {Function} callback - 要移除的回调函数,如果为 null 则移除该事件的所有监听器
|
||
|
|
*/
|
||
|
|
off: function (name: string, callback: null | Function = null) {
|
||
|
|
if (typeof name !== 'string' || !name) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 如果事件不存在,直接返回
|
||
|
|
if (!events[name] || !Array.isArray(events[name])) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 如果没有指定回调,移除该事件的所有监听器
|
||
|
|
if (callback === null) {
|
||
|
|
delete events[name];
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查找并移除指定的监听器
|
||
|
|
const index = events[name].findIndex((listener: { handler: Function }) => listener.handler === callback);
|
||
|
|
if (index !== -1) {
|
||
|
|
events[name].splice(index, 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 如果该事件没有监听器了,清理事件对象
|
||
|
|
if (events[name].length === 0) {
|
||
|
|
delete events[name];
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 触发事件
|
||
|
|
* @param {string} name - 事件名称
|
||
|
|
* @param {Object} data - 事件数据
|
||
|
|
*/
|
||
|
|
emmit: function (name: string, data: any) {
|
||
|
|
if (typeof name !== 'string' || !name) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// 如果事件不存在或没有监听器,直接返回
|
||
|
|
if (!events[name] || !Array.isArray(events[name]) || events[name].length === 0) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if ((locked[name] || false) === true) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
locked[name] = true;
|
||
|
|
|
||
|
|
// 创建 SocketMessage 实例
|
||
|
|
|
||
|
|
// 复制监听器数组,避免在执行过程中数组被修改
|
||
|
|
const listeners = [...events[name]];
|
||
|
|
|
||
|
|
// 触发所有监听器
|
||
|
|
listeners.forEach((listener, index) => {
|
||
|
|
try {
|
||
|
|
if (listener.once) {
|
||
|
|
events[name].splice(index, 1)
|
||
|
|
}
|
||
|
|
listener.handler(data);
|
||
|
|
} catch (e) {
|
||
|
|
console.log(e)
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
locked[name] = false;
|
||
|
|
|
||
|
|
delete locked[name]
|
||
|
|
},
|
||
|
|
|
||
|
|
/**
|
||
|
|
* 获取事件监听器数量(用于调试)
|
||
|
|
* @param {string} name - 事件名称,如果为空则返回所有事件的信息
|
||
|
|
*/
|
||
|
|
getListenerCount: function (name: string) {
|
||
|
|
if (name) {
|
||
|
|
return events[name] ? events[name].length : 0;
|
||
|
|
}
|
||
|
|
const result: { [key: string]: any } = {};
|
||
|
|
Object.keys(events).forEach(eventName => {
|
||
|
|
result[eventName] = events[eventName].length;
|
||
|
|
});
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})();
|