>[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
- 網絡開發