Node.js | EventEmitter(事件發射器)
EventEmitter 簡介
Node.js
所有的異步I/O
操作在完成時都會發送一個事件到事件隊列。
Node.js
裡面的許多對像都會分發事件:一個net.Server
對象會在每次有新連接時觸發一個事件,一個fs.readStream
對象會在文件被打開的時候觸發一個事件。所有這些產生事件的對像都是events.EventEmitter
的範例。
註:詳細Doc Link
EventEmitter 類
events
模組只提供了一個對象:events.EventEmitter
。EventEmitter
的核心就是事件觸發與事件監聽器功能的封裝。
你可以通過require("events");
來訪問該模組。
1 | // 引入 events 模組 |
EventEmitter
對像如果在實例化時發生錯誤,會觸發error
事件。
當添加新的監聽器時,newListener
事件會觸發,當監聽器被移除時,removeListener
事件被觸發。
下面我們用一個簡單的例子說明EventEmitter
的用法:
1 | var EventEmitter = require('events').EventEmitter; |
執行結果如下:
1 | $ node main.js |
運行這段程式,1
秒後控制台輸出了'some_event 事件觸發'
。
其原理是event
對象註冊了事件some_event
的一個監聽器,然後我們通過setTimeout
在1000
毫秒以後向event
對象發送事件 some_event
,此時會調用some_event
的監聽器。
EventEmitter
的每個事件由一個事件名和若干個參數組成,事件名是一個字符串,通常表達一定的語義。對於每個事件,EventEmitter
支持若干個事件監聽器。
當事件觸發時,註冊到這個事件的事件監聽器被依次調用,事件參數作為回調函數參數傳遞。
讓我們以下面的例子解釋這個過程:
1 | var events = require('events'); |
執行結果如下:
1 | $ node main.js |
以上例子中,emitter
為事件someEvent
註冊了兩個事件監聽器,然後觸發了someEvent
事件。
運行結果中可以看到兩個事件監聽器回調函數被先後調用。這就是EventEmitter
最簡單的用法。
EventEmitter
提供了多個屬性,如on
和emit
。
on
函數用於綁定事件函數。emit
屬性用於觸發一個事件。
具體看下EventEmitter
的屬性介紹:
方法
序號 | 方法 & 描述 | Doc |
---|---|---|
1 | addListener(eventName, listener) 為指定事件添加一個監聽器到監聽器數組的尾部。 |
Link |
2 | on(eventName, listener) 為指定事件註冊一個監聽器,接受一個字符串 event 和一個回調函數。 |
Link |
3 | once(eventName, listener) 為指定事件註冊一個單次監聽器,即 監聽器最多只會觸發一次,觸發後立刻解除該監聽器。 |
Link |
4 | removeListener(eventName, listener) 移除指定事件的某個監聽器,監聽器必須是該事件已經註冊過的監聽器。 它接受兩個參數,第一個是事件名稱,第二個是回調函數名稱。 |
Link |
5 | removeAllListeners([eventName]) 移除所有事件的所有監聽器,如果指定事件,則移除指定事件的所有監聽器。 |
Link |
6 | setMaxListeners(n) 默認情況下, EventEmitters 如果你添加的監聽器超過 10 個就會輸出警告訊息。setMaxListeners 函數用於提高監聽器的默認限制的數量。 |
Link |
7 | listeners(eventName) 返回指定事件的監聽器數組。 |
Link |
8 | emit(eventName, [arg1], [arg2], […])按監聽器的順序執行執行每個監聽器,如果事件有註冊監聽返回 true,否則返回 false。 | Link |
類方法
序號 | 方法 & 描述 | Doc |
---|---|---|
1 | listenerCount(emitter, eventName) 返回指定事件的監聽器數量。// 已廢棄,不推薦 |
Link |
2 | listenerCount(eventName) 返回指定事件的監聽器數量。// 推薦 |
Link |
事件
序號 | 方法 & 描述 | Doc |
---|---|---|
1 | newListener
|
Link |
2 | removeListener
|
Link |
範例
通過connection
(連接)事件示範了EventEmitter
類的應用。
main.js
,程式如下:
1 | var events = require('events'); |
執行結果如下:
1 | $ node main.js |
error 事件
EventEmitter
定義了一個特殊的事件error
,它包含了錯誤的語義,我們在遇到異常的時候通常會觸發error
事件。
當error
被觸發時,EventEmitter
規定如果沒有響應的監聽器,Node.js
會把它當作異常,退出程序並輸出錯誤訊息。
我們一般要為會觸發error
事件的對象設置監聽器,避免遇到錯誤後整個程序崩潰。
例如:
1 | var events = require('events'); |
執行結果如下:
1 | $ node main.js |
繼承 EventEmitter
大多數時候我們不會直接使用EventEmitter
,而是在對像中繼承它。包括fs
、net
、http
在內的,只要是支持事件響應的核心模組都是 EventEmitter
的子類。
為什麼要這樣做呢?原因有兩點:
- 首先,具有某個實體功能的對象實現事件符合語義,事件的監聽和發生應該是一個對象的方法。
- 其次
JavaScript
的對像機制是基於原型的,支持 部分多重繼承,繼承EventEmitter
不會打亂對象原有的繼承關係。
註:以上參考了
Node.js EventEmitter