如何在Node中使用自定義事件
如果你在瀏覽器中使用JavaScript,你知道多數的用戶互動是透過事件處理的,像是滑鼠點擊、鍵盤按鍵、對滑鼠移動作出反應等等。
在後端,Node給了我們使用events
模組來建立類似的系統的選項。
這個模組中,有一個EventEmitter
類別,我們會用它來處理我們的事件。
你可以使用以下語法來初始化一個EventEmitter物件:
const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
這個物件暴露了許多方法,其中包括on
和emit
。
emit
方法用於觸發一個事件。on
方法用於添加一個當事件觸發時要執行的回調函數。
觸發和監聽事件
舉個例子,我們來創建一個start
事件,作為一個示範,我們只是對它作出反應,並將其日誌記錄到控制台:
eventEmitter.on('start', () => {
console.log('started')
})
當我們執行
eventEmitter.emit('start')
事件處理函數將會被觸發,並且我們將得到控制台日誌記錄。
addListener()
是on()
的別名,如果你看到那樣的寫法,它們表示的是同一個意思。
將參數傳遞給事件
你可以通過將它們作為額外的參數傳遞給emit()
的方式,將參數傳遞給事件處理函數:
eventEmitter.on('start', (number) => {
console.log(`started ${number}`)
})
eventEmitter.emit('start', 23)
多個參數:
eventEmitter.on('start', (start, end) => {
console.log(`started from ${start} to ${end}`)
})
eventEmitter.emit('start', 1, 100)
只監聽一次事件
EventEmitter物件還提供了once()
方法,你可以使用它來創建一個一次性事件監聽器。
一旦該事件觸發,該監聽器就停止監聽。
例如:
eventEmitter.once('start', () => {
console.log(`started!`)
})
eventEmitter.emit('start')
eventEmitter.emit('start') //不會觸發
刪除事件監聽器
一旦你創建了一個事件監聽器,你可以使用removeListener()
方法來刪除它。
要這樣做,我們必須首先獲得on
的回調函數的引用。
在這個例子中:
eventEmitter.on('start', () => {
console.log('started')
})
你可以提取回調函數:
const callback = () => {
console.log('started')
}
eventEmitter.on('start', callback)
這樣以後你可以呼叫:
eventEmitter.removeListener('start', callback)
你也可以一次性刪除一個事件上的所有監聽器,使用:
eventEmitter.removeAllListeners('start')
獲取已註冊的事件
eventNames()
方法,調用在EventEmitter物件實例上,返回一個字符串陣列,表示當前EventListener上已註冊的事件:
const EventEmitter = require('events')
const eventEmitter = new EventEmitter()
eventEmitter.on('start', () => {
console.log('started')
})
eventEmitter.eventNames() // [ 'start' ]
listenerCount()
返回傳入的事件的監聽器的計數:
eventEmitter.listenerCount('start') //1
在其他監聽器之前/之後添加更多監聽
如果你有多個監聽器,它們的順序可能很重要。
EventEmitter物件實例提供了一些方法來處理順序。
emitter.prependListener()
當你使用on
或addListener
添加一個監聽器時,它被添加到監聽器隊列的最後並在最後調用。使用prependListener
,它會被添加到而且在其他監聽器之前調用。
emitter.prependOnceListener()
當你使用once
添加一個監聽器時,它被添加到監聽器隊列的最後並在最後調用。使用prependOnceListener
,它會被添加到而且在其他監聽器之前調用。