1. 程式人生 > >Node.js中的事件處理機制

Node.js中的事件處理機制

event模組是在Node.js中用以實現各種事件處理的模組。Node.js中的許多模組都集成了event模組,所以event模組是Node.js中一個相當重要的模組。而EventEmitter則是event模組唯一一個對外暴露的物件,主要用於事件的監聽和觸發所有可能觸發事件的物件都是一個繼承了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代表被解除繫結的事件處理函式
});