如何在Node中使用自定義事件

如果你在瀏覽器中使用JavaScript,你知道多數的用戶互動是透過事件處理的,像是滑鼠點擊、鍵盤按鍵、對滑鼠移動作出反應等等。

在後端,Node給了我們使用events模組來建立類似的系統的選項。

這個模組中,有一個EventEmitter類別,我們會用它來處理我們的事件。

你可以使用以下語法來初始化一個EventEmitter物件:

const EventEmitter = require('events')
const eventEmitter = new EventEmitter()

這個物件暴露了許多方法,其中包括onemit

  • 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()

當你使用onaddListener添加一個監聽器時,它被添加到監聽器隊列的最後並在最後調用。使用prependListener,它會被添加到而且在其他監聽器之前調用。

emitter.prependOnceListener()

當你使用once添加一個監聽器時,它被添加到監聽器隊列的最後並在最後調用。使用prependOnceListener,它會被添加到而且在其他監聽器之前調用。