不明白?不要緊。舉個最簡單例子,女人失戀了會哭,還會找新男友,在這裏哭和找男友至關於訂閱女人失戀的回調,何時執行呢?當發佈女人失戀這件事的時候,說的這麼抽象,直接來一段代碼吧html
// 聲明EventEmitter事件發生器構造函數
function EventEmitter() {
this._events = Object.create(null);
}
//on 訂閱方法實現 由於在實例上調用,因此寫在原型上
EventEmitter.prototype.on = function(type,callback){
// 若是實例不存在則建立一個空對象,Object.create(null)沒有鏈
if(!this._events) {
this._events = Object.create(null);
}
if(this._events[type]){ //若是失戀有對應的值,直接往數組push
this._events[type].push(callback)
}else { //第一次訂閱,沒有失戀,就聲明{失戀:[cry]}
this._events[type] = [callback];
}
};
// emit方法實現
EventEmitter.prototype.emit = function(type){
if(this._events[type]){ //{失戀:[cry,eat]} 若是失戀對應有值,依次執行裏面的方法
this._events[type].forEach(fn=>fn())
}
};
module.exports = EventEmitter
複製代碼
// 移除訂閱事件的方法
EventEmitter.prototype.removeListener = function(type,callback){
if(this._events[type]){
// 返回false就表示不要了,用filter實現去重
this._events[type] = this._events[type].filter(fn=>fn!==callback)
}
};
複製代碼
// removeAllListeners 移除全部的監聽者
EventEmitter.prototype.removeAllListeners = function(){
//簡單粗暴,直接賦值空對象 {}
this._events = Object.create(null);
};
複製代碼
// once實現
EventEmitter.prototype.once = function(type,callback,flag){
// 先綁定 調用後再刪除,運用了one函數 {失戀:one}
let one = (...args)=> {
callback(...args);
this.removeListener(type, one);
}
//自定義屬性 由於實例中沒有one屬性
one.l = callback;
this.on(type,one)
};
// 移除訂閱事件的方法
EventEmitter.prototype.removeListener = function(type,callback){
if(this._events[type]){
// 返回false就表示不要了,用filter實現去重
this._events[type] = this._events[type].filter(fn=>fn!==callback && fn.l!==callback)
}
};
複製代碼
// - 錯誤例子 錯誤例子 錯誤例子(重要事情說三遍)
//你可能會這麼寫,但剛綁定就移除拉,體會這意思了吧
EventEmitter.prototype.once = function(type,callback){
//先綁定在移除
this.on(type,callback);
this.removeListener(type,callback)
};
複製代碼
簡單說就是能夠監控到訂閱的事件類型,上源碼看下如何實現node
//on 訂閱方法實現 由於在實例上調用,因此寫在原型上
EventEmitter.prototype.on = function(type,callback){
// 若是實例不存在則建立一個空對象,Object.create(null)沒有鏈
if(!this._events) {
this._events = Object.create(null);
}
if(type!=="newListener"){
if(this._events["newListener"]){
this._events["newListener"].forEach(fn=>fn(type))
}
}
if(this._events[type]){ //若是失戀有對應的值,直接往數組push
this._events[type].push(callback)
}else { //第一次訂閱,沒有失戀,就聲明{失戀:[cry]}
this._events[type] = [callback];
}
};
複製代碼