這篇文章主要介紹怎樣模擬實現(xiàn)node中的Events模塊,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
在安順等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供做網(wǎng)站、成都網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作按需策劃設(shè)計,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計,營銷型網(wǎng)站,外貿(mào)網(wǎng)站建設(shè),安順網(wǎng)站建設(shè)費用合理。Nodejs 的大部分核心 API 都是基于異步事件驅(qū)動設(shè)計的,事件驅(qū)動核心是通過 node 中 Events 對象來實現(xiàn)事件的發(fā)送和監(jiān)聽回調(diào)綁定,我們常用的 stream 模塊也是依賴于 Events 模塊是來實現(xiàn)數(shù)據(jù)流之間的回調(diào)通知,如在數(shù)據(jù)到來時觸發(fā) data 事件,流對象為可讀狀態(tài)觸發(fā) readable 事件,當數(shù)據(jù)讀寫完畢后發(fā)送 end 事件。
既然 Events 模塊如此重要,我們有必要來學習一下 Events 模塊的基本使用,以及如何模擬實現(xiàn) Events 模塊中常用的 api
一、Events 模塊的基本使用以及簡單實現(xiàn)
首先我們了解一下 Events 模塊的基本用法,其實 Events 模塊本質(zhì)上是觀察者模式的實現(xiàn),所謂觀察者模式就是:
它定義了對象間的一種一對多的關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,當一個對象發(fā)生改變時,所有依賴于它的對象都將得到通知
觀察者模式有對應的觀察者以及被觀察的對象,在 Events 模塊中,對應的實現(xiàn)就是 on 和 emit 函數(shù)
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('嗨', (str) => { console.log(str); }); myEmitter.emit('嗨','你好');
從上述的使用中,我們可以知道 on 是用來監(jiān)聽事件的發(fā)生,而 emit 是用來觸發(fā)事件的發(fā)生,一旦 emit 觸發(fā)了事件,on 就會被通知到,從而執(zhí)行對應的回調(diào)函數(shù)。
有了這個實例,我們可以思考下如何實現(xiàn)這個 EventEmitter 類。
思路:當我們執(zhí)行 on 函數(shù)時,我們可以將回調(diào)函數(shù)保存起來,等到 emit 觸發(fā)了事件時,將回調(diào)函數(shù)拿出來執(zhí)行,那么就可以實現(xiàn)了事件的監(jiān)聽以及訂閱了。
class EventEmitter{ constructor(){ #事件監(jiān)聽函數(shù)保存的地方 this.events={}; } on(eventName,listener){ if (this.events[eventName]) { this.events[eventName].push(listener); } else { #如果沒有保存過,將回調(diào)函數(shù)保存為數(shù)組 this.events[eventName] = [listener]; } } emit(eventName){ #emit觸發(fā)事件,把回調(diào)函數(shù)拉出來執(zhí)行 this.events[eventName] && this.events[eventName].forEach(listener => listener()) } }
上述就實現(xiàn)了一個簡單的 EventEmitter 類,下面來實例一下:
let event = new EventEmitter(); event.on('嗨',function(){ console.log('你好'); }); event.emit('嗨'); #輸出:你好
完善:我們注意到在原生的 EventEmitter 類中,emit 是可以傳遞參數(shù)到我們的回調(diào)函數(shù)中,那么我們實現(xiàn)的類也應該支持傳遞參數(shù)。我們對 emit 進行如下更改
emit(eventName,...rest){ #emit觸發(fā)事件,把回調(diào)函數(shù)拉出來執(zhí)行 this.events[eventName] && this.events[eventName].forEach(listener => listener.apply(this,rest)) }
完善之后,重新實例化,如下:
let event = new EventEmitter(); event.on('嗨',function(str){ console.log(str); }); event.emit('嗨','你好'); #輸出:你好
二、Events 模塊中常用的 api
Events 模塊中除了 on、emit 函數(shù)之外,還包含了很多常用的 api,我們一一來介紹幾個實用的 api
API名稱 | API方法描述 |
---|---|
addListener(eventName, listener) | on(eventName, listener)別名,為指定事件添加一個監(jiān)聽器到監(jiān)聽器數(shù)組的尾部 |
removeListener(eventName, listener) | 從名為 eventName 的事件的監(jiān)聽器數(shù)組中移除指定的 listener |
removeAllListeners(eventName, listener) | 移除全部監(jiān)聽器或指定的 eventName 事件的監(jiān)聽器 |
once(eventName, listener) | 添加單次監(jiān)聽器 listener 到名為 eventName 的事件 |
listeners(eventName) | 返回名為 eventName 的事件的監(jiān)聽器數(shù)組的副本 |
setMaxListeners(n) | 可以為指定的 EventEmitter 實例修改監(jiān)聽器數(shù)量限制 |
1. addListener 與 on 方法使用與實現(xiàn)
在 Events 模塊中,addListener 與 on 方法的使用是完成相同的,只是名字不同,我們可以通過原型來給兩個函數(shù)建立相等關(guān)聯(lián)
EventEmitter.prototype.addListener=EventEmitter.prototype.on
2. removeListener 與 off 方法使用與實現(xiàn)
removeListener 方法可以從指定名字的監(jiān)聽器數(shù)組中移除指定的 listener,這樣的話,當再次 emit 事件的時候,不會觸發(fā) on 綁定的回調(diào)函數(shù),如下:
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); let callback = (str) => { console.log(str); } myEmitter.on('嗨', callback); myEmitter.emit('嗨','你好');#輸出:你好 myEmitter.removeListener('嗨',callback); myEmitter.emit('嗨','你好');#無輸出
實現(xiàn)思路:我們只要在執(zhí)行 removeListener 函數(shù)的時候,將先前保存的回調(diào)函數(shù)去除掉即可
removeListener (eventName,listener) { #保證回調(diào)函數(shù)數(shù)組存在,同時去除指定的listener this.events[eventName] && this.events[eventName] = this.events[eventName].filter(l => l != listener); }
同時 removeListener 與 off 方法也是功能完全相同,只是命名不同,因此可以通過如下方法賦值:
EventEmitter.prototype.removeListener=EventEmitter.prototype.off
3. removeAllListeners 方法使用與實現(xiàn)
removeAllListeners 移除全部監(jiān)聽器或指定的 eventName 事件的監(jiān)聽器,其實 removeAllListeners 就包含了 removeListener 的功能,只是 removeListener 只能指定特定的監(jiān)聽器,removeAllListeners 可以移除全部監(jiān)聽器。
實現(xiàn)思路:在執(zhí)行 removeAllListeners,將所有的回調(diào)函數(shù)都給去除即可
removeAllListeners (eventName) { #移除全部監(jiān)聽器 delete this.events[eventName] }
4. once 方法使用與實現(xiàn)
once 方法的描述是添加單次監(jiān)聽器 listener 到名為 eventName 的事件,其實就是通過 once 添加的監(jiān)聽器,只能執(zhí)行一次,執(zhí)行一次之后就會被銷毀,不能再次執(zhí)行
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.once('嗨', (str) => { console.log(str); }); myEmitter.emit('嗨','你好'); myEmitter.emit('嗨','你好'); myEmitter.emit('嗨','你好'); #只能輸出一次你好
實現(xiàn)思路:當 once 監(jiān)聽的事件回調(diào)函數(shù)執(zhí)行之后,通過 removeListener 將事件監(jiān)聽器給解綁掉,那么事件再次被 emit 的時候,就不會再次執(zhí)行回調(diào),這樣就能保證事件回調(diào)只能執(zhí)行一次
once (eventName, listener) { #重新改變監(jiān)聽回調(diào)函數(shù),使其執(zhí)行之后可以被銷毀 let reListener = (...rest) => { listener.apply(this,rest); #執(zhí)行完之后解除事件綁定 this.removeListener(type,wrapper); } this.on(eventName,reListener); }
5. listeners 方法使用與實現(xiàn)
listeners 方法返回名為 eventName 的事件的監(jiān)聽器數(shù)組的副本,其實就是獲取 eventName 中所有的回調(diào)函數(shù),這個實現(xiàn)起來很容易,就不多贅述了,代碼如下:
listeners (eventName) { return this.events[eventName] }
6. setMaxListeners 方法使用與實現(xiàn)
默認情況下,如果為特定事件添加了超過 10 個監(jiān)聽器,則 EventEmitter 會打印一個警告。 這有助于發(fā)現(xiàn)內(nèi)存泄露, 但是,并不是所有的事件都要限制 10 個監(jiān)聽器。 emitter.setMaxListeners() 方法可以為指定的 EventEmitter 實例修改限制。 值設(shè)為 Infinity(或 0)表示不限制監(jiān)聽器的數(shù)量。
const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); let callback = (str) => { console.log(str); } for (let i = 0; i <= 11; i++) { myEmitter.on('嗨', callback); } myEmitter.emit('嗨', '你好');
輸入結(jié)果如圖:
實現(xiàn)思路:
我們先將特定事件的監(jiān)聽器大設(shè)置為常量10
constructor(){ #事件監(jiān)聽函數(shù)保存的地方 this.events={}; #大監(jiān)聽器數(shù)量 this._maxListeners = 10; }
然后在我們的 on 函數(shù)中,對這個監(jiān)聽器的數(shù)量進行判斷,從而作出提示
on(eventName,listener){ if (this.events[eventName]) { this.events[eventName].push(listener); #如果超過大限度,以及不為0,則作出內(nèi)存泄漏提示 if (this._maxListeners != 0 && this.events[type].length >= this._maxListeners) { console.error('超過大的監(jiān)聽數(shù)量可能會導致內(nèi)存泄漏'); } } else { #如果沒有保存過,將回調(diào)函數(shù)保存為數(shù)組 this.events[eventName] = [listener]; } }
我們也支持對 _maxListeners 變量根據(jù)用戶的輸入進行更改,即我們的 setMaxListeners() 函數(shù)
setMaxListeners(MaxListeners) { this._maxListeners = MaxListeners }
以上是“怎樣模擬實現(xiàn)node中的Events模塊”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道!
另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。
網(wǎng)站題目:怎樣模擬實現(xiàn)node中的Events模塊-創(chuàng)新互聯(lián)
URL標題:http://www.chinadenli.net/article30/dhcepo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供自適應網(wǎng)站、建站公司、品牌網(wǎng)站制作、云服務器、品牌網(wǎng)站建設(shè)、App設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容