事件
AdonisJS 事件发射器模块构建在 Emittery 之上。它在以下方面与 Node.js 原生事件模块不同。
- 它是异步的,而 Node.js 事件模块同步发出事件。因此,请务必阅读 Emittery 对此的解释。
- 使事件类型安全的能力。
- 能够在测试期间捕获事件而不是触发实际事件。
用法
我们建议在专用文件中定义所有事件侦听器,就像在单个文件中定义路由一样。
对于本指南,让我们在start/events.ts
文件中定义事件侦听器。您可以手动创建此文件或运行以下 Ace 命令。
node ace make:prldfile events
选择所有环境
打开新创建的文件并在其中写入以下代码。Event.on
方法注册了一个事件监听器。它接受事件名称作为第一个参数,然后是处理事件的方法。
import Event from '@ioc:Adonis/Core/Event'
Event.on('new:user', (user) => {
console.log(user)
})
要触发new:user
事件侦听器,您必须提交此事件。启动后,您可以从应用程序内部的任何位置执行此操作。
import Event from '@ioc:Adonis/Core/Event'
export default class UsersController {
public async store() {
// ... 创建新用户的代码
// 高亮开始
Event.emit('new:user', { id: 1 })
// 高亮结束
}
}
使事件类型安全
事件侦听器和发出事件的代码通常不在同一个位置/文件中。因此,您的某些代码很容易发出事件并发送错误的数据。例如:
Event.on('new:user', (user) => {
console.log(user.email)
})
// 这里没有定义 email 属性
Event.emit('new:user', { id: 1 })
您可以通过在contracts/events.ts
文件中定义给定事件的参数类型来防止这种行为。
declare module '@ioc:Adonis/Core/Event' {
interface EventsList {
'new:user': { id: number; email: string }
}
}
TypeScript 静态编译器将确保对new:user
事件的所有Event.emit
调用都是类型安全的。
监听类
与控制器和中间件一样,您也可以将内联事件侦听器提取到它们的专用类中。
按照惯例,事件监听器存储在app/Listeners
目录中。不过,您可以在.adonisrc.json
文件中自定义命名空间。
Customize event listeners namespace
```json { "namespaces": { "eventListeners": "App/CustomDir/Listeners" } } ```
您可以通过运行以下 Ace 命令来创建侦听器类。
node ace make:listener User
# 创建: app/Listeners/User.ts
打开新创建的文件并在类上定义以下方法。
import { EventsList } from '@ioc:Adonis/Core/Event'
export default class User {
public async onNewUser(user: EventsList['new:user']) {
//向新用户发送电子邮件
}
}
最后,您可以将onNewUser
方法绑定为start/events.ts
文件中的事件监听器。绑定过程类似于 Route 控制器绑定,不需要定义完整的命名空间。
Event.on('new:user', 'User.onNewUser')
错误处理
当您调用Event.emit
方法时,Emittery 会异步发出事件。处理错误的一种方法是将您的发出调用包装在try/catch
块中。
try {
await Event.emit('new:user', { id: 1 })
} catch (error) {
// 处理错误
}
然而,这并不是最直观的代码编写方式。通常,您想发出事件然后忘记它们。
AdonisJS 允许您为事件发出生命周期中发生的所有错误注册一个错误处理程序,以使错误处理更容易一些。
您应该只定义一次错误处理程序(可能与其余的事件处理程序一起)。
Event.onError((event, error, eventData) => {
//处理错误
})
与 Node.js 事件发射器的区别
如前所述,AdonisJS 的 Event 模块是建立在 Emittery 之上的,它与 Node.js 的事件发射器有以下不同之处。
- Emitery 是异步的,不会阻塞事件循环。
- 它没有魔术错误事件
- 它不限制您可以为特定事件定义的侦听器数量。
-它只允许您在emit
调用期间传递 单个参数。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。