Node.js中的事件處理機制
event模組是在Node.js中用以實現各種事件處理的模組。Node.js中的許多模組都集成了event模組,所以event模組是Node.js中一個相當重要的模組。而EventEmitter則是event模組唯一一個對外暴露的物件,主要用於事件的監聽和觸發。所有可能觸發事件的物件都是一個繼承了EventEmitter類的子類物件。
文章目錄
- 1.獲取EventEmitter類
- 2.為事件新增監聽
- 3.一次性的事件監聽
- 4.設定最多可繫結的事件處理函式的數量
- 5.獲取一個事件的所有事件處理函式
- 6.為事件解綁事件處理函式
- 7.去除所有繫結的事件處理函式
- 8.手動觸發事件與自定義事件
- 9.EventEmitter類自身所擁有的事件
1.獲取EventEmitter類
通過下面程式碼即可獲得EventEmitter類。
require('event').EventEmitter;
2.為事件新增監聽
(下文的emitter代表的是集成了EventEmitter類的子類物件)。
為事件新增監聽並繫結時間處理函式,可以用emitter.on(event, handler)
或emitter.addListener(event,Handler)
let http = require('http');
let server = http.createServer();
server.on('request', (req, res)=>{
console.dir(req);
});
server.listen(2000, "localhost");
以上述程式碼為例,server就是前面提到的那個emitter,通過server.on()
方法,為server的request事件綁定了一個函式,這個函式輸出了我們對"localhost:2000"的請求的請求物件。
輸出如下:
還可以通過多個on方法來實現為一個事件繫結多個處理函式。如下所示:
let http = require('http');
let server = http.createServer();
server.on('request', (req, res)=>{
console.dir(req);
});
server.on('request', (req, res)=>{
console.log('This is another function.')
});
server.listen(2000, "localhost");
這時,除了輸出請求物件之外,還會再輸出一條"This is another function"的字串。關於多個事件處理函式執行的順序問題,函式執行的順序是按照註冊順序先後以同步方式執行。也就是說先註冊的先執行,後註冊的後執行。以上面的例子來說就是先輸出請求物件,再輸出字串。
當然了,如果在事件處理函式中使用了非同步方法,那麼也會導致非同步的執行事件處理函式。例如:
let http = require('http');
let server = http.createServer();
server.on('request', (req, res)=>{
setTimeout(()=>{
console.dir(req);
},0);
});
server.on('request', (req, res)=>{
console.log('This is another function.')
});
server.listen(2000, "localhost");
上面的結果將會是先輸出字串,後輸出請求物件。
3.一次性的事件監聽
所謂的一次性的事件監聽就是說,被繫結到事件的事件處理函式在監聽到事件發生後僅會被呼叫一次,以後再監聽到同一事件再次發生也不會再呼叫。
為了達到這個效果,我們可以使用once
方法,例如:
let http = require('http');
let server = http.createServer();
server.once('request', (req, res)=>{
console.dir(req);
});
server.listen(2000, "localhost");
上面的程式碼僅會在第一次訪問"localhost:2000"的時候觸發事件處理函式從而輸出請求物件,之後無論訪問多少次,事件處理函式都不會再被呼叫。
4.設定最多可繫結的事件處理函式的數量
上面演示瞭如何為一個事件繫結多個事件處理函式,然而,在預設情況下,我們最多隻能為一個事件設定10個處理函式,如果我們想繫結更多,就得需要setMaxListeners
方法了,使用如下:
emitter.setMaxListeners(n); //n為一個整數值
5.獲取一個事件的所有事件處理函式
如果我們希望獲得一個事件的所有事件處理函式,我們可以使用listeners
方法,使用形如:emitter.listeners(event)
(event為事件名)。例如:
let http = require('http');
let server = http.createServer();
server.on('request', (req, res)=>{
console.dir(req);
});
server.on('request', (req, res)=>{
console.log('Second');
});
server.on('request', (req, res)=>{
console.log('Third');
});
server.listen(2001, "localhost");
console.log(server.listeners('request'));
那麼輸出的結果將會是如下,
6.為事件解綁事件處理函式
有繫結就會有解除繫結,解除繫結需要使用removeListener(event, handler)
方法,引數與解除繫結一樣。不過由於需要傳入事件處理函式的名稱(第二個引數),所以匿名函式的繫結無法被解除。
let http = require('http');
let server = http.createServer();
function test(req, res){
console.dir(req);
}
server.on('request', test);
server.removeListener('request', test);
server.listen(2000, "localhost");
上面的程式碼先是為server
綁定了一個名為test
的事件處理函式,然後隨即又去除了它的繫結,那麼結果就是當server
的request事件被觸發時,test
方法將不會被觸發。
7.去除所有繫結的事件處理函式
去除所有繫結的事件處理函式,這裡包含著兩層意思。一是解除某個事件上繫結的所有事件處理函式,二是解除所有事件上所有被繫結的事件處理函式。
這兩個需求都可以通過removeAllListeners(event)
(event引數可選)來實現。**在給定了事件的時候,去除的便是這個事件被繫結的所有事件處理函式,若引數為空,則去除所有事件的所有被繫結的事件處理函式。**例如:
let http = require('http');
let server = http.createServer();
server.on('request', (req, res)=>{
setTimeout(()=>{
console.dir(req);
},0);
});
server.on('request', (req, res)=>{
console.log('This is another function.')
});
server.removeAllListeners('request');
server.listen(2000, "localhost");
8.手動觸發事件與自定義事件
8.1手動觸發事件
我們可以使用emit(event, [arg1], [arg2],..., [argn])
方法來手動觸發某個事件。event事件名引數後面的都是傳遞給該事件處理函式的引數,是可選的。
let http = require('http');
let server = http.createServer();
server.on('request', (req, res)=>{
console.dir(req);
});
server.on('request', (req, res)=>{
console.log('Second');
});
server.on('request', (req, res)=>{
console.log('Third');
});
server.emit('request', {}, {});
server.listen(2001, "localhost");
在程式碼中,我直接觸發了’request’事件,所以’request’事件上繫結的事件處理函式也都被觸發了,可以看到下圖中第一個被輸出的是一對空大括號,因為我傳遞的引數是兩個空物件(也就是此時的req和res都是空物件)。
8.2 自定義事件
自定義事件同樣是要用到emit
方法,在手動觸發事件的時候,我們需要輸入事件名
作為引數,那麼若是我們輸入的是某個自定義的事件名,如"myEvent",而且同時我們也監聽這個事件,為這個事件綁定了事件處理函式 那麼就相當於我們自定義了一個事件。例如:
let http = require('http');
let server = http.createServer();
server.on('myEvent', ()=>{
console.log('myEvent has been triggered.');
});
server.emit('myEvent');
server.listen(2000, "localhost");
9.EventEmitter類自身所擁有的事件
EventEmitter類本身也定義了兩個事件,newLIstener事件和removeListener事件。任何時候,只要對繼承了EventEmitter類的子類的例項物件繫結事件處理函式時,都將會觸發newListener事件。同樣的,在解除某個事件處理函式的繫結時,也會觸發removeListener事件。
這兩個事件為事件處理函式傳入的引數都是一樣的,如下
emitter.on('newListener', (e, f)=>{
//e代表事件名
//f代表繫結的事件處理函式
});
emitter.on('removeListener', (e, f)=>{
//e代表事件名
//f代表被解除繫結的事件處理函式
});