Node.js學(xué)習(xí)筆記:Events模塊

事件簡介

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)聽器:兩個方法removeListenerremoveAllListeners
  • 監(jiān)聽器名稱數(shù)組:getNames()
  • 監(jiān)聽器添加和移除時,分別觸發(fā)newListenerremoveListener事件。

說明

上面的內(nèi)容只是學(xué)習(xí)時候的筆記,所有內(nèi)容都可以在參考網(wǎng)址中找到。

示例代碼已發(fā)布到Github-Node

參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容