
NocoBase 服务端事件系统完全指南从app.on/db.on到emitAsync的插件级事件通信【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseNocoBase 是一个开源的无代码/低代码业务系统构建平台其服务端在应用生命周期、插件生命周期以及数据库操作等环节都会触发相应的事件Event。本篇指南以 NocoBase 官方中文文档《Event 事件》为主体结合仓库中 application.ts、database.ts、model-hook.ts 等源码实现系统讲解app.on()应用级事件、db.on()数据库级事件的注册位置、事件类型与典型用途并深入剖析emitAsync异步事件触发的底层原理帮助你在插件开发中实现扩展逻辑、自动化操作与自定义行为。一、事件系统概览两个层面一套接口NocoBase 服务端的事件系统主要分为两个层面app.on()—— 应用级事件监听应用与插件的生命周期事件比如启动、安装、启用插件等。适合做初始化逻辑、资源注册或依赖检测。db.on()—— 数据库级事件监听数据模型层面的操作事件比如创建、更新、删除记录等。适合做审计、同步、自动填充等操作。两者都继承自 Node.js 的EventEmitter因此支持标准的.on()、.off()、.emit()接口。除此之外NocoBase 还扩展了emitAsync用于异步触发事件并等待所有监听器执行完成——这一点在应用启动、插件加载等需要确保前置逻辑全部完成的场景中至关重要。从源码结构看这一设计贯穿整个核心包Application类继承自 Koa 并实现了AsyncEmitter接口声明了emitAsync见 application.tsDatabase类继承自 Node.js 的EventEmitter并同样实现AsyncEmitter声明emitAsync见 database.ts。两个类均支持同步的on/off/emit与异步的emitAsync为插件开发者提供了统一的编程模型。二、注册事件监听的位置beforeLoad()事件监听通常在插件的beforeLoad()方法中注册这样可以保证事件在插件加载阶段就已准备好后续逻辑包括其他插件、数据库操作能正确响应。import { Plugin } from nocobase/server; export default class PluginHelloServer extends Plugin { async beforeLoad() { // 监听应用事件 this.app.on(afterStart, () { app.logger.info(NocoBase 已启动); }); // 监听数据库事件 this.db.on(afterCreate, (model) { if (model.collectionName posts) { app.logger.info(新帖子${model.get(title)}); } }); } }从源码调用链看插件加载流程会先执行所有插件的beforeLoad()再逐个执行load()见 plugin-manager.ts。因此在beforeLoad()中注册的监听器一定早于应用启动事件与任何数据操作事件被触发这是官方推荐在此注册的根本原因。三、监听应用事件app.on()应用事件用于捕获 NocoBase 应用及插件的生命周期变化适合做初始化逻辑、资源注册或依赖检测等。3.1 常见事件类型事件名称触发时机典型用途beforeLoad/afterLoad应用加载前 / 后注册资源、初始化配置beforeStart/afterStart服务启动前 / 后启动任务、打印启动日志beforeInstall/afterInstall应用安装前 / 后初始化数据、导入模板beforeStop/afterStop服务停止前 / 后清理资源、保存状态beforeDestroy/afterDestroy应用销毁前 / 后删除缓存、断开连接beforeLoadPlugin/afterLoadPlugin插件加载前 / 后修改插件配置或扩展功能beforeEnablePlugin/afterEnablePlugin插件启用前 / 后检查依赖、初始化插件逻辑beforeDisablePlugin/afterDisablePlugin插件禁用前 / 后清理插件资源afterUpgrade应用升级完成后执行数据迁移或兼容性修复3.2 典型示例监听应用启动事件app.on(afterStart, async () { app.logger.info(NocoBase 服务已启动); });监听插件加载事件afterLoadPlugin的回调参数中会携带plugin实例app.on(afterLoadPlugin, ({ plugin }) { app.logger.info(插件 ${plugin.name} 已加载); });3.3 源码级证据这些事件在哪里被触发以上事件并非文档虚构而是真实存在于核心包的启动流程中并且全部通过emitAsync触发意味着监听器中的异步逻辑会被完整等待启动事件Application.start()中依次执行await this.emitAsync(beforeStart, this, options)与await this.emitAsync(afterStart, this, options)见 application.ts停止事件应用重初始化时依次触发beforeStop与afterStop确保旧实例资源被清理见 application.ts插件事件插件管理器在plugin.beforeLoad()前后触发beforeLoadPlugin/afterLoadPlugin在启用、禁用插件的流程中分别触发beforeEnablePlugin/afterEnablePlugin、beforeDisablePlugin/afterDisablePlugin见 plugin-manager.ts升级事件应用升级完成后触发afterUpgrade见 application.ts。这些触发点同时也被官方测试覆盖例如 application.test.ts 中直接注册beforeInstall监听器验证安装流程sync-message.test.ts 中通过app.emitAsync(afterStart)等调用验证生命周期事件链路。如果你想验证自己的监听器是否生效也可以参考这些测试的写法。四、监听数据库事件db.on()数据库事件用于捕获模型层的各种数据变更适合做审计、同步、自动填充等操作。4.1 常见事件类型事件名称触发时机beforeSync/afterSync同步数据库结构前 / 后beforeValidate/afterValidate数据校验前 / 后beforeCreate/afterCreate创建记录前 / 后beforeUpdate/afterUpdate更新记录前 / 后beforeSave/afterSave保存前 / 后含创建和更新beforeDestroy/afterDestroy删除记录前 / 后afterCreateWithAssociations/afterUpdateWithAssociations/afterSaveWithAssociations操作包含关联数据后beforeDefineCollection/afterDefineCollection定义集合前 / 后beforeRemoveCollection/afterRemoveCollection删除集合前 / 后4.2 典型示例监听数据创建后事件db.on(afterCreate, async (model, options) { db.logger.info(数据已创建); });监听更新数据前事件db.on(beforeUpdate, async (model, options) { db.logger.info(数据即将更新); });4.3 源码级证据模型事件、全局事件与关联事件数据库事件并非简单的自触发其底层桥接了 Sequelize 的 hook 机制。核心实现在 model-hook.tsModelHook.buildSequelizeHook构造的 hook 会在每个 Sequelize 生命周期钩子触发时先尝试从参数中解析出模型名通过_previousDataValues、model或modelName等特征识别见 model-hook.ts若解析成功先触发模型级事件await this.database.emitAsync(\${modelName}.${type}, ...args)再触发全局事件await this.database.emitAsync(type, ...args)。这意味着监听器拥有两档粒度全局监听db.on(afterCreate, ...)捕获所有集合的创建事件模型级监听db.on(posts.afterCreate, ...)只捕获posts集合的创建事件实现更精确的过滤避免在回调里反复判断model.collectionName。此外通过 Repository 层执行的数据操作还会额外触发“带关联”系列事件。例如 repository.ts 在创建主记录并处理完关联数据后会依次触发afterCreateWithAssociations与afterSaveWithAssociations更新流程同理见 repository.ts。这类事件保证了你监听到的是一条连同关联字段一起完整落库的记录非常适合做跨集合的联动逻辑。4.4 事务与上下文参数所有数据库事件监听器的第二个参数options中通常包含transaction当前事务对象等上下文信息。在监听器中执行新的数据操作时建议沿用该事务保证监听逻辑与主操作保持原子性同时也应避免在监听器内发起同表的写操作造成递归触发必要时可通过options.context或业务字段做幂等控制。五、emitAsync异步事件触发的关键机制emitAsync是 NocoBase 事件系统区别于普通 Node.jsEventEmitter的核心扩展。它的行为是触发事件后等待所有监听器包括 async 函数执行完毕再继续后续流程。它的意义可以从一个场景理解如果在beforeStart里注册了一个需要联网或读写数据库的异步初始化任务使用同步emit时该任务尚未完成、应用就可能已经开始对外服务而emitAsync会阻塞启动流程直到所有监听器完成确保“启动完成”的语义是真实的。这一点在源码中处处可见应用启动流程用await this.emitAsync(afterStart, ...)启动日志、初始化任务都能在afterStart全部完成后才进入就绪状态插件加载流程用await this.emitAsync(afterLoadPlugin, plugin, options)保证后续插件的加载能依赖前面监听器已经完成的工作多应用模式下主应用会通过app.emitAsync(event, payload)将生命周期事件广播给子应用见 main-only-adapter.ts。因此当你的监听器是 async 函数且需要确保顺序时请依赖emitAsync触发的内置生命周期事件而emit适合不需要等待、纯“通知式”的场景。六、实战建议与注意事项综合官方文档与源码实现在实际插件开发中建议遵循以下原则统一在beforeLoad()注册监听器确保监听器先于所有生命周期事件和数据操作就绪优先使用模型级事件能用db.on(posts.afterCreate, ...)就不用db.on(afterCreate, ...)再手动过滤代码更清晰、性能更好异步监听器依赖emitAsync语义内置生命周期事件均为异步等待可以在监听器中放心执行异步任务处理关联数据时监听 WithAssociations 系列事件需要拿到包含关联字段完整数据时使用afterCreateWithAssociations等事件避免监听器内的递归写操作在afterCreate中再次写同一集合会导致事件重入需通过条件判断或上下文标记防止死循环及时解绑若监听器生命周期短于应用例如按条件动态注册记得用off()解绑防止重复执行。七、相关文档与源码索引Plugin 插件 — 在插件生命周期方法中注册事件监听Database 数据库操作 — 数据库级事件的触发源与数据操作 APICollections 数据表 — 数据表定义与数据库事件中的模型关系Middleware 中间件 — 中间件与事件在请求处理中的协作服务端开发概述 — 事件系统在服务端架构中的角色关键源码位置应用事件定义与触发packages/core/server/src/application.ts数据库事件定义与触发packages/core/database/src/database.tsSequelize hook 与事件桥接packages/core/database/src/model-hook.ts插件生命周期事件触发packages/core/server/src/plugin-manager/plugin-manager.ts关联数据事件触发packages/core/database/src/repository.ts【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考