EventEmitter 是什么
- Node.js 的
events 模塊
對外提供了一個EventEmitter 對象
,用于對 Node.js 中的事件進行統(tǒng)一管理。- Node.js 采用了事件驅(qū)動機制蔬崩, EventEmitter 就是 Node.js 實現(xiàn)事件驅(qū)動的基礎(chǔ)连茧,Node.js 中幾乎所有的模塊都繼承了這個類,以實現(xiàn)異步事件驅(qū)動架構(gòu)产场。
- Node.js 中幾乎所有的模塊都繼承了這個類唆姐,以實現(xiàn)異步事件驅(qū)動架構(gòu)拗慨。瀏覽器事件(如鼠標(biāo)單擊click廓八,鍵盤事件keyDown)等都是該模式的例子
核心代碼-參考1
使用 events 模塊奉芦,對事件數(shù)組進行管理,
on
添加進事件隊列 addListener
emit
執(zhí)行
off
關(guān)閉 removeListener
once
只執(zhí)行一次剧蹂,結(jié)束后 remove
class EventEmitter {
constructor(){
this.events = {}
}
on(event, listener){
let listeners = this.events[event] || []
listeners.push(listener)
this.events = listeners
return this
}
emit(event, ...args){
let listeners = this.events[event]
listeners.forEach(listener => {
listener(...args)
});
return this
}
off(event, listener){
let listeners = this.events[event]
this.events[event] = listeners && listeners.filter(fn => fn !== listener)
return this
}
once(event, listener){
let fn = function(...args){
listener(...args)
this.off(event, listener)
}
this.on(event, fn)
return this
}
}
優(yōu)化-參考2
添加事件合法性校驗等
function EventEmitter() {
this.__events = {};
}
EventEmitter.VERSION = "1.0.0";
EventEmitter.prototype.on = function (eventName, listener) {
// 驗證參數(shù)
if (!eventName && !listener) {
return;
}
// 回調(diào)的litener是否是函數(shù)
if (!isValidKistener(listener)) {
throw new TypeError("listener must be a function");
}
const events = this.__evnets;
const listeners = (events[eventName] = evnets[eventName] || []);
const listenerIsWrapped = typeof listener === "object";
// 不重復(fù)添加事件声功,判斷是否有相同
if (indexOf(listeners.listener) === -1) {
listeners.push(
listenerIsWrapped
? listener
: {
listener: listener,
once: false,
}
);
}
return this;
};
//判斷是否是合法的listener
const isValidListener = (listener) => {
if (typeof listener === "function") {
return true;
} else if (listener && typeof listener === "object") {
return isValidListener(listener.listener);
} else {
return false;
}
};
// 判斷新增自定義事件是否存在
const indexOf = (array, item) => {
let result = -1;
item = typeof item === "object" ? item.listener : item;
for (let i = 0; i < array.length; i++) {
if (array[i].listener === item) {
result = i;
break;
}
}
return result;
};
設(shè)計模式
采用了發(fā)布-訂閱者模式
發(fā)布-訂閱模式
其實是一種對象間一對多
的依賴關(guān)系,當(dāng)一個對象的狀態(tài)發(fā)送改變時宠叼,所有依賴于它的對象都將得到狀態(tài)改變的通知先巴。
- 訂閱者(Subscriber)把自己想訂閱的事件 注冊(Subscribe)到調(diào)度中心(Event Channel);
- 當(dāng)發(fā)布者(Publisher)發(fā)布該事件(Publish Event)到調(diào)度中心其爵,也就是該事件觸發(fā)時,由 調(diào)度中心 統(tǒng)一調(diào)度(Fire Event)訂閱者注冊到調(diào)度中心的處理代碼
相關(guān)文章