Skip to Content

事件与动作

Entity Engine 的事件与动作系统让您可以构建响应式和自动化的应用。当数据发生变化时,事件会自动触发相关的业务逻辑;而动作则让您可以封装可重用的业务操作。

事件用于”通知发生了什么”,动作用于”执行具体操作”。两者结合使用,可以构建出强大而灵活的业务流程。

快速开始

监听数据变化

Entity Engine 会在数据发生变化时自动触发事件。您只需要监听这些事件并添加自己的业务逻辑:

import { getEntityEngine } from './lib/entity-engine'; const engine = await getEntityEngine(); // 监听用户创建事件 engine.eventRegistry.on('entityObject.created', async (event) => { if (event.modelName === 'User') { console.log(`新用户注册: ${event.values.name}`); // 发送欢迎邮件 await sendWelcomeEmail(event.values.email); // 创建用户配置 await createUserProfile(event.objectId); } });

这样设置后,每当有新用户注册时,系统会自动发送欢迎邮件并创建用户配置。

创建自定义动作

动作是可重用的业务操作,可以在不同地方调用:

// 注册发布文章动作 engine.actionRegistry.registerAction('blog.publish', async (context) => { const { postId } = context.input; // 更新文章状态 await engine.datasource.updateObject({ id: postId, values: { status: 'published', publishedAt: new Date() } }); return { success: true, postId }; }); // 在任何地方调用动作 const result = await engine.actionRegistry.executeAction('blog.publish', { input: { postId: 'post-123' } });

内置事件

数据生命周期事件

Entity Engine 在数据操作时会自动触发这些事件:

// 监听所有数据创建事件 engine.eventRegistry.on('entityObject.created', (event) => { console.log(`创建了新的 ${event.modelName}: ${event.objectId}`); }); // 监听数据更新事件 engine.eventRegistry.on('entityObject.updated', (event) => { console.log(`更新了 ${event.modelName}: ${event.objectId}`); console.log('变更内容:', event.changes); }); // 监听数据删除事件 engine.eventRegistry.on('entityObject.deleted', (event) => { console.log(`删除了 ${event.modelName}: ${event.objectId}`); });

配置变更事件

当系统配置发生变化时也会触发事件:

// 监听模型配置变更 engine.eventRegistry.on('config.updated', (event) => { if (event.key.startsWith('model:')) { console.log(`模型配置已更新: ${event.key}`); // 重新加载相关缓存 refreshModelCache(event.key); } });

业务场景应用

订单处理流程

使用事件和动作可以轻松构建复杂的业务流程:

// 1. 监听订单创建 engine.eventRegistry.on('entityObject.created', async (event) => { if (event.modelName === 'Order') { // 自动处理新订单 await engine.actionRegistry.executeAction('order.process', { input: { orderId: event.objectId } }); } }); // 2. 注册订单处理动作 engine.actionRegistry.registerAction('order.process', async (context) => { const { orderId } = context.input; // 检查库存 const inventoryOk = await checkInventory(orderId); if (!inventoryOk) { throw new Error('库存不足'); } // 处理支付 const paymentResult = await processPayment(orderId); if (!paymentResult.success) { throw new Error('支付失败'); } // 更新订单状态 await engine.datasource.updateObject({ id: orderId, values: { status: 'paid' } }); return { success: true, orderId }; });

用户行为跟踪

跟踪用户行为并触发相应的营销活动:

// 跟踪用户活动 engine.eventRegistry.on('entityObject.created', async (event) => { if (event.modelName === 'UserActivity') { const activity = event.values; // 如果用户连续7天活跃,发送奖励 if (activity.type === 'login') { const consecutiveDays = await getConsecutiveLoginDays(activity.userId); if (consecutiveDays === 7) { await engine.actionRegistry.executeAction('user.sendReward', { input: { userId: activity.userId, reason: '连续登录7天' } }); } } } });

触发自定义事件

业务事件通知

您可以在业务逻辑中触发自定义事件来通知其他模块:

// 在业务逻辑中触发事件 async function completeOrder(orderId: string) { // 完成订单处理 await updateOrderStatus(orderId, 'completed'); // 触发订单完成事件 await engine.eventRegistry.emit('order.completed', { orderId, completedAt: new Date(), metadata: { source: 'manual' } }); } // 其他模块监听这个事件 engine.eventRegistry.on('order.completed', async (event) => { // 发送完成通知 await sendOrderCompletionEmail(event.orderId); // 更新用户积分 await updateUserPoints(event.orderId); // 生成发票 await generateInvoice(event.orderId); });

跨模块通信

事件系统特别适合模块间的解耦通信:

// 支付模块触发事件 await engine.eventRegistry.emit('payment.success', { orderId: '123', amount: 299.99, paymentMethod: 'credit_card' }); // 库存模块监听并处理 engine.eventRegistry.on('payment.success', async (event) => { await reduceInventory(event.orderId); }); // 通知模块监听并处理 engine.eventRegistry.on('payment.success', async (event) => { await sendPaymentConfirmation(event.orderId); });

动作的高级用法

带权限的动作

动作可以包含权限检查,确保只有授权用户才能执行:

engine.actionRegistry.registerAction('blog.delete', async (context) => { const { postId } = context.input; const { user } = context; // 检查用户权限 const hasPermission = await engine.permissionManager.checkModelPermission( 'Post', 'delete', { user } ); if (!hasPermission) { throw new Error('权限不足'); } // 执行删除 await engine.datasource.deleteObject({ id: postId }); return { success: true, deletedId: postId }; }, { description: '删除博客文章', permissions: ['blog:delete'] });

参数验证

使用 Zod 验证动作的输入参数:

import { z } from 'zod'; engine.actionRegistry.registerAction('user.updateProfile', async (context) => { const { userId, profile } = context.input; await engine.datasource.updateObject({ id: userId, values: profile }); return { success: true, userId }; }, { description: '更新用户资料', inputSchema: z.object({ userId: z.string(), profile: z.object({ name: z.string().min(1, '姓名不能为空'), email: z.string().email('邮箱格式无效'), age: z.number().min(0, '年龄不能为负数').optional() }) }) });

事件与动作的协作

事件触发动作链

一个事件可以触发多个动作,形成完整的业务流程:

// 监听用户注册事件 engine.eventRegistry.on('entityObject.created', async (event) => { if (event.modelName === 'User') { const userId = event.objectId; // 触发一系列后续动作 await Promise.all([ engine.actionRegistry.executeAction('user.sendWelcome', { input: { userId } }), engine.actionRegistry.executeAction('user.createProfile', { input: { userId, email: event.values.email } }), engine.actionRegistry.executeAction('analytics.trackSignup', { input: { userId, source: event.values.signupSource } }) ]); } });

动作触发事件

动作执行完成后也可以触发事件:

engine.actionRegistry.registerAction('order.ship', async (context) => { const { orderId } = context.input; // 执行发货逻辑 const trackingNumber = await shipOrder(orderId); // 更新订单状态 await engine.datasource.updateObject({ id: orderId, values: { status: 'shipped', trackingNumber, shippedAt: new Date() } }); // 触发发货事件 await engine.eventRegistry.emit('order.shipped', { orderId, trackingNumber, shippedAt: new Date() }); return { success: true, trackingNumber }; });

错误处理

事件监听器错误

事件监听器中的错误不会影响其他监听器:

engine.eventRegistry.on('entityObject.created', async (event) => { try { await sendNotification(event); } catch (error) { console.error('发送通知失败:', error); // 记录失败,但不阻止其他处理 await logError('notification_failed', { event: event.type, objectId: event.objectId, error: error.message }); } });

动作执行错误

动作执行失败时应该返回标准化的错误响应:

engine.actionRegistry.registerAction('payment.process', async (context) => { try { const result = await processPayment(context.input); return { success: true, data: result }; } catch (error) { console.error('支付处理失败:', error); return { success: false, error: '支付处理失败', details: error.message, retryable: error.code === 'NETWORK_ERROR' }; } });

性能优化

异步处理

对于耗时的操作,使用后台处理避免阻塞主流程:

engine.eventRegistry.on('entityObject.created', async (event) => { if (event.modelName === 'User') { // 快速响应的操作 await createUserSession(event.objectId); // 耗时操作放到后台处理 setImmediate(async () => { try { await generateUserReport(event.objectId); await syncToExternalSystem(event.objectId); } catch (error) { console.error('后台处理失败:', error); } }); } });

条件过滤

在事件监听器开头添加条件检查,避免不必要的处理:

engine.eventRegistry.on('entityObject.updated', async (event) => { // 只处理状态变更 if (!event.changes.status) { return; } // 只处理订单状态变更 if (event.modelName !== 'Order') { return; } // 执行状态变更处理逻辑 await handleOrderStatusChange(event); });

最佳实践

事件命名规范

使用清晰的命名约定来组织事件:

// ✅ 推荐:使用分层命名 'user.registered' // 用户相关事件 'user.profileUpdated' 'order.created' // 订单相关事件 'order.statusChanged' 'payment.success' // 支付相关事件 'payment.failed' // ❌ 避免:模糊的命名 'userEvent' 'orderThing' 'somethingHappened'

动作设计原则

动作应该是原子的、可重用的操作:

// ✅ 推荐:原子操作 'user.sendEmail' // 发送邮件 'order.updateStatus' // 更新订单状态 'inventory.reduce' // 减少库存 // ❌ 避免:复合操作 'user.registerAndSendEmailAndCreateProfile' // 太复杂

解耦设计

使用事件实现模块间的松耦合:

// ✅ 推荐:通过事件解耦 // 用户模块只负责用户注册 async function registerUser(userData) { const user = await createUser(userData); await engine.eventRegistry.emit('user.registered', { userId: user.id }); return user; } // 邮件模块独立处理 engine.eventRegistry.on('user.registered', async (event) => { await sendWelcomeEmail(event.userId); }); // ❌ 避免:直接依赖 async function registerUser(userData) { const user = await createUser(userData); await sendWelcomeEmail(user.id); // 直接依赖邮件模块 return user; }

调试和监控

事件日志

记录事件的触发和处理情况:

engine.eventRegistry.on('*', (event) => { console.log('事件触发:', { type: event.type, timestamp: new Date(), data: event }); });

动作执行监控

监控动作的执行时间和成功率:

const originalExecuteAction = engine.actionRegistry.executeAction; engine.actionRegistry.executeAction = async function(actionName, context) { const startTime = Date.now(); try { const result = await originalExecuteAction.call(this, actionName, context); // 记录成功执行 console.log('动作执行成功:', { action: actionName, duration: Date.now() - startTime, success: true }); return result; } catch (error) { // 记录执行失败 console.error('动作执行失败:', { action: actionName, duration: Date.now() - startTime, error: error.message }); throw error; } };

下一步

掌握事件与动作系统后,您可以:

Last updated on