>[success] # events模块
1. `Node`中的核心API都是基于异步事件驱动的,自带的`events`模块它可以用于处理**Node.js中的事件**
2. Node.js中的`events`模块就是一种**发布订阅(publish/subscribe)模式的实现**。`events`模块通过**EventEmitter类**实现了这种**发布订阅模式**,使得不同的模块之间可以**相互通信、传递消息,从而实现模块之间的高效耦合 在这个体系中**,某些对象(发射器(Emitters))发出某一个事件;我们可以监听这个事件(监听器 Listeners),并且传入的回调函数,这个回调函数会在监听到事件时调用;
3. 在实际开发中,events 模块常常被用来作为解耦合、扩展代码等方面
4. events模块 **优点的地方**
| 优点 | 例子 |
| --- | --- |
| 异步处理 | 在Node.js中,I/O 操作是异步的操作,使用events模块可以方便地处理这些异步事件,从而提高系统的性能和可扩展性。例如,http服务器监听客户端请求事件('request'),或者文件系统触发读取文件完成事件('read')。 |
| 灵活性 | 使用events模块时,可以自定义事件。例如,我们可以在设置同步操作成功或失败后触发一个'operation complete'事件,从而让其他模块更好地监听这个事件来执行相应的操作。 |
| 易用性 | events模块提供了简单的API,例如on()和emit()来实现事件处理和触发。同时,它也提供了其他方便使用的方法,例如once()和removeListener()来监听和移除事件监听器。 |
5. events模块 **缺点的地方**
| 缺点 | 例子 |
| --- | --- |
| 存在内存泄漏 | 如果我们没有正确地移除事件监听器,会导致内存泄漏。所以,我们必须注意在不再需要使用事件时,及时移除事件监听器。例如,在程序中使用 eventEmitter.on()监听事件,但是忘了使用eventEmitter.off()或者removeListener()移除监听器。 |
| 可读性差 | 如果我们没有合理地使用events模块,例如定义过多的事件名称,可能会导致代码可读性较差,难以维护和修改。例如,定义了名为'operation complete','operation finished','task complete','work done'等多个事件名称,会导致事件名称的使用较为混乱。 |
>[info] ## node 中常见使用
在 Node.js 中,有很多内置的 API 使用了 events 模块提供的事件机制。下面是一些常见的内置 API:
* Stream:所有的可读流和可写流都是 EventEmitter 的实例,它们可以触发多个事件(如 'data' 事件,'end' 事件等),通知应用程序数据可用(或无法使用)等情况。
* HTTP 模块:HTTP 模块返回的服务器和客户端都是 EventEmitter 的实例,可以处理请求和响应事件以及错误和关闭事件。
* Child Processes(子进程):子进程的对象都是 EventEmitter 的实例,可以监听 'exit' 事件来检测子进程何时结束,以及 stdout 和 stderr 中的数据事件。
* File System 模块:文件操作模块也使用了事件,如读取文件时会触发 'data' 事件、'end' 事件等。
除此之外,还有一些其他的 Node.js API 使用了 events 模块,如`readline`模块、`dns`模块等。了解这些内置 API 使用的事件机制,可以帮助你更好地理解和应用 events 模块。
>[info] ## 常用的api
1. 使用常用的`api`之前需要先声明一个 `EventEmitter` 类,然后使用 `EventEmitter`类对外提供的`api`
~~~
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
~~~
2. 注册事件监听器 使用on()方法来注册一个事件监听器,语法如下:
~~~
eventEmitter.on(eventName, listener);
~~~
其中eventName参数指定要监听的事件名称,listener参数是一个回调函数,当事件触发时会被调用。
3. 触发事件使用emit()方法来触发一个事件,语法如下:
~~~
eventEmitter.emit(eventName, [args]);
~~~
其中 eventName参数指定要触发的事件名称,args参数是一个可选的数组,它包含传递给监听器的参数。
下面是一个简单的示例,演示了如何使用 events 模块:
~~~
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
//注册事件监听器
eventEmitter.on('eventName', function listener() {
console.log('event has occurred');
});
//触发事件
eventEmitter.emit('eventName');
~~~
当运行这段代码时,控制台将输出 'event has occurred'。
* **常用api方法**
| 方法名 | 参数 | 返回值 | 描述 |
| --- | --- | --- | --- |
| on(eventName, listener) / addListener(eventName, listener) | eventName: Stringlistener: Function | EventEmitter对象 | 监听事件,当对应的事件触发时,执行回调函数 |
| once(eventName, listener) | eventName: Stringlistener: Function | EventEmitter对象 | 监听一次事件,事件被触发后将被删除 |
| prependListener(eventName, listener) | eventName: Stringlistener: Function | EventEmitter对象 | 将监听事件添加到最前面 |
| prependOnceListener(eventName, listener) | eventName: Stringlistener: Function | EventEmitter对象 | 将监听事件添加到最前面,但是只监听一次 |
| removeListener(eventName, listener) | eventName: Stringlistener: Function(可选) | EventEmitter对象 | 移除事件监听器,若不指定listener则移除所有该事件的监听器 |
| removeAllListeners(\[eventName\]) | eventName: String(可选) | EventEmitter对象 | 移除所有或指定事件的所有监听器 |
| listeners(eventName) | eventName: String | Array | 返回指定事件的监听器数组 |
| emit(eventName\[, ...args\]) | eventName: String...args: any | Boolean | 触发事件,调用对应事件的所有监听器并传入参数 |
| off(eventName, listener) / removeListener(eventName, listener) | eventName: Stringlistener: Function(可选) | EventEmitter对象 | 移除事件监听器,与removeListener一样 |
| eventNames() | | Array | 返回当前 EventEmitter对象注册的事件字符串数组 |
| getMaxListeners() | | Number | 返回当前 EventEmitter对象的最大监听器数量,默认是10。可以通过setMaxListeners()方法修改 |
| listenerCount(eventName) | eventName: String | Number | 返回当前 EventEmitter对象某一事件的监听器个数 |
>[danger] ##### 案例
~~~
const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
// 定一个监听方法
function listener1(name, age) {
console.log('监听器 listener1 执行', name, age)
}
function listener2(name, age) {
console.log('监听器 listener1 执行', name, age)
}
// 注册监听事件
eventEmitter.on('onEvent', listener1)
// 注册只触发一次的监听事件
eventEmitter.once('onEvent', listener2)
// prependListener 设置监听器的优先级将给定的监听器函数添加到名为 eventName 的事件的监听器数组的开头。
eventEmitter.prependListener('onEvent', () => {
console.log('我变成第一个触发的了prependListener')
})
// 我虽然插到前面,但是我只触发一次
eventEmitter.prependOnceListener('onEvent', () => {
console.log('我变成第一个触发的了prependOnceListener')
})
// 触发事件
eventEmitter.emit('onEvent', '张三', 18)
// 再次触发
eventEmitter.emit('onEvent', '张三', 18)
~~~
* 执行顺序
我变成第一个触发的了prependOnceListener
我变成第一个触发的了prependListener
监听器 listener1 执行 张三 18
监听器 listener1 执行 张三 18
我变成第一个触发的了prependListener
监听器 listener1 执行 张三 18
~~~
const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
// 定一个监听方法
function listener1(name, age) {
console.log('监听器 listener1 执行', name, age)
}
function listener2(name, age) {
console.log('监听器 listener2 执行', name, age)
}
// 注册监听事件
eventEmitter.on('onEvent', listener1)
eventEmitter.on('onEvent', listener2)
// 移除指定方法的监听事件
// eventEmitter.off('onEvent', listener1) //等同于removeListener
eventEmitter.removeListener('onEvent', listener1)
// 想移除所有的监听事件
// eventEmitter.removeAllListeners('onEvent')
eventEmitter.emit('onEvent', '张三', 18) // 监听器 listener2 执行 张三 18
~~~
~~~
const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
// 定一个监听方法
function listener1(name, age) {
console.log('监听器 listener1 执行', name, age)
}
function listener2(name, age) {
console.log('监听器 listener2 执行', name, age)
}
// 注册监听事件
eventEmitter.on('onEvent', listener1)
eventEmitter.on('onEvent', listener2)
// 打印监听器方法列表
const ls = eventEmitter.listeners('onEvent')
console.log(ls)
~~~
~~~
const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
// 定一个监听方法
function listener1(name, age) {
console.log('监听器 listener1 执行', name, age)
}
function listener2(name, age) {
console.log('监听器 listener2 执行', name, age)
}
// 注册监听事件
eventEmitter.on('onEvent', listener1)
eventEmitter.on('onEvent', listener2)
eventEmitter.on('bbb', listener2)
// 返回当前 EventEmitter对象注册的事件字符串数组
const ls = eventEmitter.eventNames()
console.log(ls) // [ 'onEvent', 'bbb' ]
~~~
~~~
const EventEmitter = require('events')
const ee = new EventEmitter()
ee.on("aaa", () => {})
ee.on("aaa", () => {})
ee.on("aaa", () => {})
ee.on('bbb', () => {})
ee.on('bbb', () => {})
// 1.获取所有监听事件的名称
console.log(ee.eventNames())
// 2.获取监听最大的监听个数
console.log(ee.getMaxListeners())
// 3.获取某一个事件名称对应的监听器个数
console.log(ee.listenerCount('aaa'))
// 4.获取某一个事件名称对应的监听器函数(数组)
console.log(ee.listeners('aaa'))
~~~
- 基础
- 什么是Node.js
- 理解 I/O 模型
- 理解node 中 I/O
- 对比node 和java 使用场景
- node 模块管理
- 内置模块 -- buffer
- 内置模块 -- fs
- fs -- 文件描述符
- fs -- 打开文件 api
- fs -- 文件读取 api
- fs -- 文件写入 api
- fs -- 创建目录 api
- fs -- 读取文件目录结构 api
- fs -- 文件状态(信息) api
- fs -- 删除文件/目录 api
- fs -- 重命名 api
- fs -- 复制文件 api
- 内置模块 -- events
- 内置模块 -- stream
- 可读流 -- Readable
- 可写流 -- Writable
- Duplex
- Transform
- 内置模块 -- http
- http -- 从客户端发起
- http -- 从服务端发起
- 内置模块 -- url
- 网络开发