🎯 Handler 模块
约 1169 字大约 4 分钟
2025-05-15
注
本文由 AI 辅助生成,可能存在不准确性。
Handler 模块提供了事件处理器的调用机制,允许插件注册和处理特定事件,并通过键值对的方式进行查找和调用。该模块是实现插件间通信和事件处理的核心组件。
模块概述
Handler 模块主要用于处理注册到特定事件键上的处理函数。它提供了一种插件可以互相调用功能的机制,支持断处理流程。
API 接口
handler
调用事件处理器。支持直接调用、使用 call 方法调用以及使用 has 方法检查是否存在处理器。
import { handler } from 'node-karin'
import type { Event } from 'node-karin'
/**
* 调用事件处理器
* @param key 事件键
* @param args 自定义参数,如果传递事件对象需要使用e字段
* @returns 处理器返回的结果
*/
// 直接调用
const result1 = await handler('event.key', { param1: 'value1', e: eventObject })
// 使用call方法调用(可以指定返回类型)
const result2 = await handler.call<string>('event.key', { param1: 'value1' })
// 检查是否存在处理器
const hasHandler = handler.has('event.key')
handler.call
与直接调用 handler 功能相同,但允许显式指定返回类型。
import { UserInfo } from 'node-karin'
import { handler } from 'node-karin'
/**
* 调用事件处理器
* @param key 事件键
* @param args 自定义参数
* @returns 处理器返回的结果
*/
const result = await handler.call<UserInfo>('user.get', { userId: '123456' })
// result的类型被指定为UserInfo
handler.has
检查是否存在指定键的事件处理器。
import { handler } from 'node-karin'
/**
* 检查是否存在指定键的事件处理器
* @param key 事件键
* @returns 是否存在处理器
*/
if (handler.has('permission.check')) {
// 存在权限检查处理器,可以调用
const hasPermission = await handler('permission.check', { userId: '123456', action: 'edit' })
}
事件处理器机制
事件处理器使用了一种特殊的调用机制,允许多个处理器注册到同一个事件键上,并且可以决定是否继续执行链中的下一个处理器。
处理器注册
处理器通常通过插件系统注册到特定的事件键上。每个处理器函数接收两个参数:
args
:调用处理器时传递的参数对象next
:一个函数,调用它表示当前处理器不处理此事件,允许继续执行链中的下一个处理器
处理流程
当调用handler
函数时,它会按照注册顺序遍历所有匹配指定键的处理器:
- 如果处理器不调用
next()
并返回一个值,该值将作为整个handler
调用的返回值,处理链终止 - 如果处理器调用
next()
,则处理器的返回值会被忽略,继续执行链中的下一个处理器 - 如果所有处理器都调用了
next()
或没有任何处理器注册,则返回undefined
处理器可以返回一个 Promise,Handler 模块会自动等待它完成。
使用示例
基本使用
import { handler } from 'node-karin'
// 检查用户权限
async function checkUserPermission (userId: string, action: string) {
if (!handler.has('permission.check')) {
// 没有权限处理器,默认拒绝
return false
}
return await handler('permission.check', { userId, action })
}
// 使用示例
async function editUserProfile (userId: string, newData: any) {
// 检查是否有编辑权限
const hasPermission = await checkUserPermission(userId, 'profile.edit')
if (!hasPermission) {
throw new Error('没有权限编辑个人资料')
}
// 有权限,执行编辑操作
return await handler('user.edit', { userId, data: newData })
}
与事件系统结合
import karin, { handler } from 'node-karin'
// 使用 karin.command 处理消息命令
export const translateCommand = karin.command(/^\/translate (.+)$/, async (e, next) => {
// 从正则匹配中获取要翻译的文本
const text = e.msg.match(/^\/translate (.+)$/)?.[1]
if (!text) {
await e.reply('请提供要翻译的文本')
return
}
// 检查是否有翻译处理器
if (handler.has('translate.text')) {
// 调用翻译处理器
const translated = await handler('translate.text', {
text,
from: 'auto',
to: 'zh-CN',
e,
})
// 将翻译结果发送回去
if (translated) {
await e.reply(`翻译结果: ${translated}`)
return // 处理完成,不继续匹配
}
}
await e.reply('翻译服务暂不可用')
})
注意事项
- 处理器注册顺序:处理器按注册顺序执行,先注册的处理器优先级更高
- 错误处理:如果处理器抛出异常,Handler 模块会捕获它并继续执行链中的下一个处理器
- 类型安全:使用
handler.call<T>
可以指定返回类型,提高代码的类型安全性 - 性能考虑:在处理大量事件时,应确保处理器函数高效执行,避免阻塞事件循环