local EventBus = {}
-- 事件监听器存储
local listeners = {}
-- 订阅事件
function EventBus:Subscribe(eventName, callback, priority)
if not eventName or not callback then
SL:Print("错误:事件名称和回调函数不能为空")
return false
end
if not listeners
🤖 回答引擎: 前端Lua |
🕒 时间: 2026-06-03 11:27:59 |
👁️ 阅读: 15
这段代码是一个基础的事件总线框架,实现得不错,但有几个地方可以优化,让它在996引擎里更稳定、更易用。
**主要优点:**
1. 结构清晰,订阅、分发、取消订阅功能都齐全
2. 有优先级排序,能控制回调执行顺序
3. 用了`pcall`包裹回调,有错误处理
**几个可以改进的地方:**
**1. 打印函数问题**
代码里用了`SL:Print`,但根据浮生梦老师前端课程内容,正确的打印函数是`SL:print`(注意是小写)。
```lua
-- 修改前
SL:Print("错误:事件名称和回调函数不能为空")
-- 修改后
SL:print("错误:事件名称和回调函数不能为空")
```
**2. 潜在的性能问题**
每次订阅都调用`table.sort`排序,如果监听器很多会影响性能。可以改成只在需要时排序,或者用更高效的数据结构。
**3. 事件名称类型检查**
`tostring(eventName)`虽然能处理多种类型,但在引擎环境下,明确的事件名称(字符串)更可靠,可以增加类型检查。
**4. 时间戳的用途**
你添加了`timestamp`字段,但代码里没用到。如果是为了调试或按订阅时间排序,可以在排序规则里加上。
**优化后的订阅函数示例:**
```lua
function EventBus:Subscribe(eventName, callback, priority)
-- 增加类型检查
if type(eventName) ~= "string" or eventName == "" then
SL:print("错误:事件名称必须是有效字符串")
return false
end
if type(callback) ~= "function" then
SL:print("错误:回调函数必须是函数类型")
return false
end
if not listeners[eventName] then
listeners[eventName] = {}
end
priority = priority or 0
local timestamp = os.time()
table.insert(listeners[eventName], {
callback = callback,
priority = priority,
timestamp = timestamp
})
-- 标记需要重新排序(实际实现可以用标志位控制)
self._needSort = true
SL:print(string.format("事件 [%s] 订阅成功", eventName))
return true
end
```
**使用建议:**
这个框架适合用在模块间通信,比如:
- UI界面状态变化通知其他组件
- 游戏状态改变(登录、升级、获得物品)触发事件
- 网络消息分发到各个处理模块
**注意:** 在996引擎里,如果事件和引擎内置事件重名可能会冲突,建议给你的事件加个前缀,比如`"UI_OPEN"`改成`"MYMODULE_UI_OPEN"`。
总体来说框架思路正确,稍微调整下就能在实际项目中使用了。记得测试下多个监听器同时触发的情况哦!
这段代码是一个基础的事件总线框架,实现得不错,但有几个地方可以优化,让它在996引擎里更稳定、更易用。
**主要优点:**
1. 结构清晰,订阅、分发、取消订阅功能都齐全
2. 有优先级排序,能控制回调执行顺序
3. 用了`pcall`包裹回调,有错误处理
**几个可以改进的地方:**
**1. 打印函数问题**
代码里用了`SL:Print`,但根据浮生梦老师前端课程内容,正确的打印函数是`SL:print`(注意是小写)。
```lua
-- 修改前
SL:Print("错误:事件名称和回调函数不能为空")
-- 修改后
SL:print("错误:事件名称和回调函数不能为空")
```
**2. 潜在的性能问题**
每次订阅都调用`table.sort`排序,如果监听器很多会影响性能。可以改成只在需要时排序,或者用更高效的数据结构。
**3. 事件名称类型检查**
`tostring(eventName)`虽然能处理多种类型,但在引擎环境下,明确的事件名称(字符串)更可靠,可以增加类型检查。
**4. 时间戳的用途**
你添加了`timestamp`字段,但代码里没用到。如果是为了调试或按订阅时间排序,可以在排序规则里加上。
**优化后的订阅函数示例:**
```lua
function EventBus:Subscribe(eventName, callback, priority)
-- 增加类型检查
if type(eventName) ~= "string" or eventName == "" then
SL:print("错误:事件名称必须是有效字符串")
return false
end
if type(callback) ~= "function" then
SL:print("错误:回调函数必须是函数类型")
return false
end
if not listeners[eventName] then
listeners[eventName] = {}
end
priority = priority or 0
local timestamp = os.time()
table.insert(listeners[eventName], {
callback = callback,
priority = priority,
timestamp = timestamp
})
-- 标记需要重新排序(实际实现可以用标志位控制)
self._needSort = true
SL:print(string.format("事件 [%s] 订阅成功", eventName))
return true
end
```
**使用建议:**
这个框架适合用在模块间通信,比如:
- UI界面状态变化通知其他组件
- 游戏状态改变(登录、升级、获得物品)触发事件
- 网络消息分发到各个处理模块
**注意:** 在996引擎里,如果事件和引擎内置事件重名可能会冲突,建议给你的事件加个前缀,比如`"UI_OPEN"`改成`"MYMODULE_UI_OPEN"`。
总体来说框架思路正确,稍微调整下就能在实际项目中使用了。记得测试下多个监听器同时触发的情况哦!
← 返回问答库