事件簡介
Node.js 是單進(jìn)程單線程應(yīng)用程序,但是因?yàn)?V8 引擎提供的異步執(zhí)行回調(diào)接口,通過這些接口可以處理大量的并發(fā),所以性能非常高。
Node.js 幾乎每一個 API 都是支持回調(diào)函數(shù)的。
Node.js 基本上所有的事件機(jī)制都是用設(shè)計(jì)模式中觀察者模式實(shí)現(xiàn)。
Node.js 單線程類似進(jìn)入一個while(true)的事件循環(huán),直到?jīng)]有事件觀察者退出,每個異步事件都生成一個事件觀察者,如果有事件發(fā)生就調(diào)用該回調(diào)函數(shù).
事件驅(qū)動
Node.js 使用事件驅(qū)動模型,當(dāng)web server接收到請求,就把它關(guān)閉然后進(jìn)行處理,然后去服務(wù)下一個web請求。當(dāng)這個請求完成,它被放回處理隊(duì)列,當(dāng)?shù)竭_(dá)隊(duì)列開頭,這個結(jié)果被返回給用戶。這個模型非常高效可擴(kuò)展性非常強(qiáng),因?yàn)閣ebserver一直接受請求而不等待任何讀寫操作。(這也被稱之為非阻塞式IO或者事件驅(qū)動IO)
事件循環(huán)圖

Events模塊
大多數(shù) Node.js 核心 API 都采用慣用的異步事件驅(qū)動架構(gòu),其中某些類型的對象(觸發(fā)器)會周期性地觸發(fā)命名事件來調(diào)用函數(shù)對象(監(jiān)聽器)。
所有能觸發(fā)事件的對象都是 EventEmitter 類的實(shí)例。 這些對象開放了一個 eventEmitter.on() 函數(shù),允許將一個或多個函數(shù)綁定到會被對象觸發(fā)的命名事件上。 事件名稱通常是駝峰式的字符串,但也可以使用任何有效的 JavaScript 屬性名。
當(dāng) EventEmitter 對象觸發(fā)一個事件時,所有綁定在該事件上的函數(shù)都被同步地調(diào)用。 監(jiān)聽器的返回值會被丟棄。
使用events模塊
const EventEmitter = require('events')
示例代碼
第一個例子,一個綁定了一個監(jiān)聽器的EventEmitter實(shí)例。
const EventEmitter = require('events') // 引入事件模塊
const event = new EventEmitter() // 創(chuàng)建實(shí)例
// 注冊監(jiān)聽器
event.on('event', () => {
console.log('觸發(fā)了一個事件!')
})
// 觸發(fā)事件
event.emit('event')
// > 執(zhí)行和結(jié)果
// node test_01.js
// 觸發(fā)了一個事件!
關(guān)于監(jiān)控器中的this
eventEmitter.emit() 方法允許將任意參數(shù)傳給監(jiān)聽器函數(shù)。 當(dāng)一個普通的監(jiān)聽器函數(shù)被 EventEmitter 調(diào)用時,標(biāo)準(zhǔn)的 this 關(guān)鍵詞會被設(shè)置指向監(jiān)聽器所附加的 EventEmitter。也可以使用 ES6 的箭頭函數(shù)作為監(jiān)聽器。但是這樣 this 關(guān)鍵詞就不再指向 EventEmitter 實(shí)例。
下面通過代碼理解
// 注冊監(jiān)聽器,并接受內(nèi)容
event.on('message', (message) => {
console.log('接收到的信息:' + message);
})
// 觸發(fā)
event.emit('message', 'Hello world')
// 輸出:接收到的信息:Hello world
// 注意
// 使用ES6的箭頭函數(shù)時,this不再執(zhí)行events實(shí)例。
// 做個測試
event.on('test1', function () {
console.log('this的指向:')
console.log(this)
})
event.emit('test1')
// this的指向:
// EventEmitter {
// _events:
// { event: [Function],
// message: [Function],
// test1: [Function],
// test2: [Function] },
// _eventsCount: 4,
// _maxListeners: undefined }
event.on('test2', () => {
console.log('this的指向:')
console.log(this)
})
event.emit('test2')
// this的指向:
// {}
只執(zhí)行一次
多次觸發(fā)事件會重復(fù)執(zhí)行監(jiān)聽函數(shù),使用once代替on,實(shí)現(xiàn)只監(jiān)聽一次。
let count = 0
event.on('add', () => {
console.log(++count)
})
event.emit('add')
// count = 1
event.emit('add')
// count = 2
let onceCount = 0
event.once('once', () => {
console.log(++onceCount) // 先 加 1 在輸出
})
event.emit('once')
// 1
event.emit('once')
// 忽略
其他
- 監(jiān)聽器數(shù)量:默認(rèn)情況下,特定事件添加超過10個監(jiān)聽器,就會出現(xiàn)警告??梢酝ㄟ^
setMaxListeners()方法修改限制。 - 移除監(jiān)聽器:兩個方法
removeListener和removeAllListeners。 - 監(jiān)聽器名稱數(shù)組:getNames()
- 監(jiān)聽器添加和移除時,分別觸發(fā)
newListener和removeListener事件。
說明
上面的內(nèi)容只是學(xué)習(xí)時候的筆記,所有內(nèi)容都可以在參考網(wǎng)址中找到。
示例代碼已發(fā)布到Github-Node