mm_event
v2.0.0
Published
这是一个事件机制, 用于构建网站路由事件、游戏事件、实现对消息拦截、分发、修改、记录、统计
Downloads
12
Maintainers
Readme
mm_event
这是一个功能完整的事件机制模块,用于构建网站路由事件、游戏事件、实现对消息拦截、分发、修改、记录、统计等功能。
功能特点
- 支持发布-订阅模式的主题订阅系统
- 提供完整的事件生命周期管理(before、check、main、render、after)
- 全面支持异步操作(async/await、Promise)
- 增强的错误处理机制
- 提供防抖(debounce)和节流(throttle)功能
- 优化的性能设计
安装
npm install mm_event基本使用
const mm_event = require('mm_event');
// 创建事件实例
const ev = new mm_event({
errorPropagation: true, // 是否传播错误
debug: false // 是否开启调试模式
});
// 监听事件
eval.on('/api/user/info', 'before', function(ctx, db, options) {
console.log('执行前处理', ctx);
});
// 一次性事件(执行一次后自动删除)
eval.once('/api/user/info', 'main', function(ctx, db) {
console.log('只执行一次', ctx);
return {success: true, data: {id: 1, name: 'test'}};
});
// 订阅主题
eval.subscribe('/api/user/info', function(type, msg) {
console.log('收到订阅通知', type, msg);
});
// 执行事件
const result = await ev.run('/api/user/info', {query: {user_id: 1}});
console.log('执行结果', result);
// 取消订阅
eval.unsubscribe('/api/user/info');高级功能示例
防抖功能示例
// 防抖搜索 - 只有用户停止输入300ms后才执行搜索
let searchCount = 0;
eval.debounce('/search/user', 'main', function(ctx, db) {
searchCount++;
console.log(`执行搜索: ${ctx.keyword}, 执行次数: ${searchCount}`);
return {results: [`找到用户: ${ctx.keyword}`]};
}, 300);
// 连续触发多次,但只会执行一次
await ev.run('/search/user', {keyword: 'test1'});
await ev.run('/search/user', {keyword: 'test2'});
await ev.run('/search/user', {keyword: 'test3'});
// 300ms后,只有最后一次触发会执行,searchCount = 1节流功能示例
// 节流处理 - 每500ms最多执行一次
let scrollCount = 0;
eval.throttle('/window/scroll', 'main', function(ctx, db) {
scrollCount++;
console.log(`处理滚动事件,位置: ${ctx.position}, 执行次数: ${scrollCount}`);
return {processed: true};
}, 500);
// 连续触发,但会按时间间隔执行
await ev.run('/window/scroll', {position: 100});
// 100ms后
await ev.run('/window/scroll', {position: 200});
// 100ms后
await ev.run('/window/scroll', {position: 300});
// 最终会执行多次,但间隔至少500ms主题解绑示例
// 绑定多个事件到同一主题
eval.on('/dynamic/theme', 'main', function(ctx) { return '处理结果1'; });
eval.on('/dynamic/theme', 'after', function(ctx) { console.log('处理结果2'); });
// 执行事件,会触发所有绑定的处理函数
const result = await ev.run('/dynamic/theme', {});
// 解绑整个主题的所有事件和订阅
eval.unbind('/dynamic/theme');
// 再次执行,不会触发任何处理函数
const result2 = await ev.run('/dynamic/theme', {});API 文档
构造函数
new mm_event(config)config: 配置对象errorPropagation: 是否传播错误,默认为truedebug: 是否开启调试模式,默认为false
事件监听
on - 设置事件
await ev.on(topic, stage, func, options = null, sort = 100, state = 1, name = '')topic: 事件主题stage: 事件阶段,可选值:before、check、main、render、afterfunc: 回调函数,格式:function(ctx, db, options)options: 配置参数sort: 排序值,越小越先执行state: 状态,0为不启用,1为启用name: 自定义事件名称
once - 设置一次性事件
await ev.once(topic, stage, func, options = null, sort = 100, state = 1)参数同on方法,但会在执行一次后自动删除
debounce - 防抖事件
await ev.debounce(topic, stage, func, wait, options = null, sort = 100)wait: 等待时间(毫秒)- 功能说明: 防抖功能可以确保在指定时间内连续触发的事件只执行一次。当事件被触发后,如果在等待时间内再次触发,则重新计时。适用于需要限制频繁触发的场景,如搜索输入、窗口调整等。
throttle - 节流事件
await ev.throttle(topic, stage, func, limit, options = null, sort = 100)limit: 限制时间(毫秒)- 功能说明: 节流功能可以控制事件触发的频率,确保在指定时间间隔内最多只执行一次。与防抖不同,节流会在指定时间间隔内定期执行,而不是等待最后一次触发后才执行。适用于需要定期执行但又不能过于频繁的场景,如滚动事件处理、拖拽操作等。
事件管理
del - 删除事件
await ev.del(topic, stage, name)get - 获取事件
await ev.get(topic, stage, name)clear - 清空事件
await ev.clear(topic, stage)- 只传topic时清空该主题的所有阶段
- 同时传topic和stage时只清空指定阶段
unbind - 解绑主题
await ev.unbind(topic)- 功能说明: 解绑指定主题的所有事件和订阅,包括所有阶段的事件处理器。解绑后,再次执行该主题的事件将不再触发任何回调函数。适用于需要完全移除某个主题相关的所有处理逻辑的场景。
事件执行
run - 执行事件
await ev.run(topic, ctx, db = {})ctx: 上下文对象db: 数据管理器
发布订阅
subscribe - 订阅主题
await ev.subscribe(topic, func, name = '')unsubscribe - 取消订阅
await ev.unsubscribe(topic, name)- 只传topic时取消该主题的所有订阅
- 同时传topic和name时只取消指定订阅
send - 推送订阅内容
await ev.send(topic, type, msg)事件生命周期
- before: 执行前,用于改变参数和统计
- check: 校验,用于鉴权,有返回值则中断执行
- main: 主要业务逻辑,有返回值则继续执行render阶段
- render: 渲染,用于改变回复内容
- after: 执行后,用于过滤回复,或回复内容转发,或者记录
错误处理
可以通过options设置自定义错误处理回调:
eval.on('/api/user/info', 'main', function(ctx, db) {
throw new Error('测试错误');
}, {
onError: function(err, ctx, db) {
console.log('自定义错误处理', err);
db.errorHandled = true;
}
});调试模式
开启调试模式可以获得更详细的错误信息:
const ev = new mm_event({debug: true});贡献
欢迎提交Issue和Pull Request!
许可证
ISC
