Node中EventEmitter理解與簡單實現

背景

node的招牌技能是「事件驅動,非阻塞IO」,能夠看到事件在node中的重要性。
在瀏覽器端存在各類事件綁定(click、mousedown...),node中也存在各類事件綁定(fs.read、http.creaeServer...)。
在node中還有一個自定義事件EventEmitter,官網寫到不少node的api都是基於EventEmitter。node

使用

通常咱們會經過繼承來使用EventsEmitter,單獨new一個EventEmitter彷佛除了驗證方法沒有意義。api

//引入events模塊
const EventEmitter = require('events');
//定義一個MyEmitter類繼承EventEmiteer
class MyEmitter extends EventEmitter {}

//new一個MyEmitter對象
const myEmitter = new MyEmitter();
//給myEmitter對象綁定一個event事件
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
//觸發event事件
myEmitter.emit('event');    //輸出 "an event occurred!"
複製代碼

這裏咱們實現對EventEmitter繼承,綁定事件監聽函數,觸發事件。數組

EventEmitter簡單實現

簡單原理:在EventEmitter下建立一個events對象。以on監聽的事件名爲鍵名,鍵值是監聽的函數的組合爲一個數組。瀏覽器

1.建立EventEmitter對象bash

function EventEmitter() {
    this.events = {};  //全部事件監聽函數放在這個對象裏保存
    this._maxListeners = 10; //監聽函數最多10個
}
複製代碼

2.給EventEmitter增長on、addEventListener綁定事件app

//給制定函數綁定事件處理函數
EventEmitter.prototype.on = EventEmitter.prototype.addEventListener = function (type,listener) {
    if(this.events[type]){
        this.events[type].push(listener);
        if(this._maxListeners != 0 && this.events[type].length > this._maxListeners){
            console.error('MaxListenersExceededWarning: Possible EventEmitter memory leak detected.\n');
        }
    }else {
        this.events[type] = [listener];
    }
}

複製代碼

3.觸發事件函數

EventEmitter.prototype.emit = function (type, ...rest) {
    if(this.events[type]){
        //遍歷觸發函數數組   apply把this指向當前對象  解構rest
        this.events[type].forEach((listener)=>listener.apply(this,rest));
    }
}
複製代碼

4.移除監聽函數ui

EventEmitter.prototype.removeListener =  function(type,listener) {
   if (this.events[type]){
       this.events[type] = this.events[type].filter(l=>l!=listener);
       //使用filter過濾數組
   }
}
複製代碼

簡單的EventEmitter模型實現完成,歡迎點評交流。this

相關文章
相關標籤/搜索