Nodejs 的大部分核心 API 都是基于異步事件驅動設計的,事件驅動核心是通過 node 中 Events 對象來實現事件的發送和監聽回調綁定,我們常用的 stream 模塊也是依賴于 Events 模塊是來實現數據流之間的回調通知,如在數據到來時觸發 data 事件,流對象為可讀狀態觸發 readable 事件,當數據讀寫完畢后發送 end 事件。
既然 Events 模塊如此重要,我們有必要來學習一下 Events 模塊的基本使用,以及如何模擬實現 Events 模塊中常用的 api
一、Events 模塊的基本使用以及簡單實現
首先我們了解一下 Events 模塊的基本用法,其實 Events 模塊本質上是觀察者模式的實現,所謂觀察者模式就是:
它定義了對象間的一種一對多的關系,讓多個觀察者對象同時監聽某一個主題對象,當一個對象發生改變時,所有依賴于它的對象都將得到通知
觀察者模式有對應的觀察者以及被觀察的對象,在 Events 模塊中,對應的實現就是 on 和 emit 函數
const EventEmitter = require('events');class MyEmitter extends EventEmitter {}const myEmitter = new MyEmitter();myEmitter.on('嗨', (str) => { console.log(str);});myEmitter.emit('嗨','你好');從上述的使用中,我們可以知道 on 是用來監聽事件的發生,而 emit 是用來觸發事件的發生,一旦 emit 觸發了事件,on 就會被通知到,從而執行對應的回調函數。
有了這個實例,我們可以思考下如何實現這個 EventEmitter 類。
思路:當我們執行 on 函數時,我們可以將回調函數保存起來,等到 emit 觸發了事件時,將回調函數拿出來執行,那么就可以實現了事件的監聽以及訂閱了。
class EventEmitter{ constructor(){ #事件監聽函數保存的地方 this.events={}; } on(eventName,listener){ if (this.events[eventName]) { this.events[eventName].push(listener); } else { #如果沒有保存過,將回調函數保存為數組 this.events[eventName] = [listener]; } } emit(eventName){ #emit觸發事件,把回調函數拉出來執行 this.events[eventName] && this.events[eventName].forEach(listener => listener()) }}上述就實現了一個簡單的 EventEmitter 類,下面來實例一下:
let event = new EventEmitter();event.on('嗨',function(){ console.log('你好');});event.emit('嗨');#輸出:你好完善:我們注意到在原生的 EventEmitter 類中,emit 是可以傳遞參數到我們的回調函數中,那么我們實現的類也應該支持傳遞參數。我們對 emit 進行如下更改
emit(eventName,...rest){ #emit觸發事件,把回調函數拉出來執行 this.events[eventName] && this.events[eventName].forEach(listener => listener.apply(this,rest))}
新聞熱點
疑難解答
圖片精選