天天看點

Node 中的Event子產品詳解

Events是Node最重要的子產品,它提供了一個對象events.EventEmitter,EventEmitter 的核心是事件發射與事件監聽器。

Node.js中大部分的子產品,都繼承自Event子產品。

EventEmitter 支援若幹個事件監聽器,當事件發射時,注冊到這個事件的事件監聽器被依次調用,事件參數作為回調函數參數傳遞。

事件子產品相關的方法主要有以下這些:

1. EventEmitter.on(event, listener)

注冊監聽事件。

參數1:event  事件名;

參數2:listener 回調函數;

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter; 
// 執行個體化EventEmitter對象  
var ee = new EventEmitter();

// 注冊監聽事件someEvents
ee.on('someEvents', function(a, b) {
    console.log("觸發了監聽事件,參數為1為" + a + ",參數2為" + b );
});

// 第1次觸發事件someEvents
ee.emit('someEvents', 'time', 'address');
// 觸發了監聽事件,參數為1為time,參數2為address

// 第2次觸發事件someEvents
ee.emit('someEvents', 'name', 'age');
// 觸發了監聽事件,參數為1為name,參數2為age           

複制

2. EventEmitter.emit(event, [arg1], [arg2], [...]) 

觸發指定的監聽事件。

參數1:event  事件名;

參數2:[arg1] 可選參數,按順序傳入回調函數的參數;

傳回值:該事件是否有監聽;

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter;
// 執行個體化EventEmitter對象  
var ee = new EventEmitter();

// 第1次注冊監聽事件someEvents
ee.on('someEvents', function (a, b) {
    console.log("觸發了第1個監聽事件,參數為1為" + a + ",參數2為" + b);
});

// 觸發事件someEvents并傳回布爾類型的結果值
var resultA = ee.emit('someEvents', 'time', 'address');
// 觸發了第1個監聽事件,參數為1為time,參數2為address

// 第2次注冊監聽事件someEvents
ee.on('someEvents', function (a, b) {
    console.log("觸發了第2個監聽事件,參數為1為" + a + ",參數2為" + b);
});

// 觸發監聽事件someEvents
ee.emit('someEvents', 'name', 'age');
// 觸發了第1個監聽事件,參數為1為time,參數2為address
// 觸發了第2個監聽事件,參數為1為time,參數2為address


// 嘗試觸發一個未注冊的監聽事件并傳回布爾類型的結果值
var resultB = ee.emit('otherEvents', 'page', 'pagesize');

console.log(resultA);
// true
console.log(resultB);
// false           

複制

3. EventEmitter.once(event, listener)  

為事件注冊一次性監聽,觸發一次後移除監聽事件,後續再次觸發将無效。

參數1:event  事件名;

參數2:listener 回調函數;

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter;   
// 執行個體化EventEmitter對象 
var ee = new EventEmitter();


// 注冊一次性監聽事件someEvents
ee.once('someEvents', function(a, b) {
    console.log("觸發了監聽事件,參數為1為" + a + ",參數2為" + b);
});

// 觸發一次性監聽事件
ee.emit('someEvents', 'time', 'address');
// 觸發了監聽事件,參數為1為time,參數2為address

// 再次觸發監聽事件,并傳回布爾結果值
var result =  ee.emit('someEvents', 'name', 'age');

console.log(result);
// false           

複制

4. EventEmitter.removeListener(event, listener)  

移除指定事件的監聽器,注意:該監聽器必須是注冊過的。

參數1:event  事件名;

參數2:listener 回調函數;

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter;   
// 執行個體化EventEmitter對象  
var ee = new EventEmitter();


// 監聽事件1
var listener1 = function(a,b){
    console.log("觸發了第1個監聽事件,參數為1為" + a + ",參數2為" + b);
}

// 監聽事件2
var listener2= function(a,b){
    console.log("觸發了第2個監聽事件,參數為1為" + a + ",參數2為" + b);
}

// 監聽事件3
var listener3= function(a,b){
    console.log("觸發了第3個監聽事件,參數為1為" + a + ",參數2為" + b);
};

// 注冊監聽事件1
ee.on('someEvents', listener1);
// 注冊監聽事件2
ee.on('someEvents', listener2);
// 注冊監聽事件3
ee.on('someEvents', listener3);


// 移除監聽事件1
ee.removeListener('someEvents', listener1);
// 移除監聽事件2
ee.removeListener('someEvents', listener2);

// 觸發監聽事件
ee.emit('someEvents', 'time', 'address');
// 觸發了第3個監聽事件,參數為1為time,參數2為address           

複制

5. EventEmitter.removeAllListeners([event])   

移除(批定事件)所有監聽器,一個事件可以有多個監聽,需要全部移除時,可以用此方法。

參數1:event  事件名 可選參數。

需要特别注意的是,如果不傳參數,将會移除所有的監聽事件,比較暴力,建議慎用。

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter; 
// 執行個體化EventEmitter對象    
var ee = new EventEmitter();

// 監聽事件1
var listener1 = function(a,b){
    console.log("觸發了第1個監聽事件,參數為1為" + a + ",參數2為" + b);
};
// 監聽事件2
var listener2= function(a,b){
    console.log("觸發了第2個監聽事件,參數為1為" + a + ",參數2為" + b);
};

// 注冊監聽事件1
ee.on('someEvents', listener1);
// 注冊監聽事件2
ee.on('someEvents', listener2);

// 注冊監聽另一個事件
ee.on('otherEvents',function(a,b){
    console.log("觸發了另1個監聽事件,參數為1為" + a + ",參數2為" + b);
});

// 移除所有的注冊監聽事件someEvents
ee.removeAllListeners('someEvents');

// 觸發監聽事件someEvents
ee.emit('someEvents', 'time', 'address');

// 觸發另一個監聽事件otherEvents
ee.emit('otherEvents', 'name', 'age');
// 觸發了另1個監聽事件,參數為1為name,參數2為age           

複制

6. EventEmitter.listeners(event)   

傳回指定事件的注冊監聽的集合。

參數1:event 事件名 。

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter;
// 執行個體化EventEmitter對象    
var ee = new EventEmitter();


// 監聽事件1
var listener1 = function (a, b) {
    console.log("觸發了第1個監聽事件,參數為1為" + a + ",參數2為" + b);
};
// 監聽事件2
var listener2 = function (a, b) {
    console.log("觸發了第2個監聽事件,參數為1為" + a + ",參數2為" + b);
};


// 注冊監聽事件1
ee.on('someEvents', listener1);
// 注冊監聽事件2
ee.on('someEvents', listener2);



// 注冊監聽另一個事件
ee.on('otherEvents', function (a, b) {
    console.log("觸發了另1個監聽事件,參數為1為" + a + ",參數2為" + b);
});

// 擷取指定事件的監聽數組
var listenerEventsArr = ee.listeners('someEvents');


for (var i = 0; i < listenerEventsArr.length; i++) {
    // 列印輸出監聽事件
    console.log(listenerEventsArr[i]);

    // [Function: listener1]
    // [Function: listener2]

};           

複制

7. EventEmitter.setMaxListeners (n)  

給EventEmitter設定最大監聽數。

參數1: n  數字最大監聽數。

正常情況下,可以設定的最大監聽數為10個,如果超過了10個,就會出現警告,以下代碼可以驗證。

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter;
// 執行個體化EventEmitter對象    
var ee = new EventEmitter();

//  給EventEmitter 添加11個監聽
for (var i = 0; i <= 10; i++) {
    ee.on('someEvents',function(){
        console.log('第'+ (i +1) +'個監聽');
    });
};           

複制

執行結果出現了如下的警告:

Warning: Possible EventEmitter memory leak detected. 11 someEvents listeners added. Use emitter.setMaxListeners() to increase limit。

系統認為偵聽器太多,可能導緻記憶體洩漏,是以存在這樣一個警告,并且給出了提示,讓我們用 emitter.setMaxListeners()  去提升限制。

// 調用events子產品,擷取events.EventEmitter對象
var EventEmitter = require('events').EventEmitter;
// 執行個體化EventEmitter對象    
var ee = new EventEmitter();

// 設定最大監聽數為16個
ee.setMaxListeners(16);

//  給EventEmitter 添加11個監聽
for (var i = 0; i <= 10; i++) {
    ee.on('someEvents',function(){
        console.log('第'+ (i +1) +'個監聽');
    });
};

var listenerEventsArr = ee.listeners('someEvents');

// 列印輸出監聽事件數量
console.log(listenerEventsArr.length);
// 11           

複制

不知道為什麼,11個事件是添加成功了,但是回調裡沒有列印輸出,歡迎大家在評論區讨論!

8. EventEmitter.defaultMaxListeners (n)  

給所有EventEmitter設定最大監聽,功能與setMaxListeners類似,不過setMaxListeners優先級要大于defaultMaxListeners,用的比較少,就不細說了。

9. EventEmitter.listenerCount(emitter, event)

傳回指定事件的監聽數,用的比較少,就不細說了。