Nodejs中不存在瀏覽器中冒泡,捕獲這些行為,Nodejs中實現了events這個模塊,Nodejs中大多數模塊都集成了這個模塊,所以events是Nodejs中最重要的一個模塊。
events只對外暴露一個對象,就是EventEmitter,EventEmitter作用只有2個,分別是:事件的發射和事件的監聽。
Node.js中,很多對象會發出事件。如,fs.readStream打開文件時會發出一個事件。
所有發出事件的對象都是events.EventEmitter的實例,可以通過require("event");獲得event模塊。
監聽器函數(listeners)可以添加給對象,對象發出事件時,對應的函數就會被執行。在監聽器函數中,this引用的是它(監聽器函數)
一、Class:events.EventEmitter
通過require('events').EventEmitter得到EventEmitter類。
當EventEmitter對象遇到錯誤時,通常會觸發error事件。error事件在Nodejs中是一種特殊情況,如果沒有監聽器,那么默認會打印出棧跟蹤器並退出程序。
二、添加監聽器
為事件綁定事件處理程序,可以用emitter.addListener(event,listener)和emitter.on(event,listener),它們作用完全一樣。傳入參數是事件(event)和處理函數(listener)。
demo:test1.js內容如下
var http = require('http'); var server = http.createServer(); // 為request事件綁定處理函數 // 也可以使用server.addListener server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou'); console.log('shiyanlou'); res.end(); }); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
三、只執行一次的監聽器
使用 emitter.once(event,listener)綁定的事件監聽器只執行一次,然后就會被刪除掉。
demo:test2.js內容如下
var http = require('http'); var server = http.createServer(); // 為request事件綁定處理函數,事件只會執行一次 server.once('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou'); console.log('shiyanlou'); res.end(); }); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
四、移除監聽器
移除監聽器使用emitter.removeListener(event,listener);
demo:test3.js內容如下
var http = require('http'); var server = http.createServer(); function callback(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('Hello World'); console.log('Hello World'); res.end(); } server.on('request', callback); // 移除綁定的監聽器callback server.removeListener('request', callback); server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou'); console.log('shiyanlou'); res.end(); }); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
運行結果只顯示shiyanliu,不顯示hello world,因為“hello world”的監聽器被移除了。
錯誤的移除事件不能移除匿名的事件處理程序,必須像上面一樣移除具名函數。
server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou'); console.log('shiyanlou'); res.end(); }); //錯誤的移除事件方法 server.removeListener('request',function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou'); console.log('shiyanlou'); res.end(); });
五、移除所有監聽器
移除所有監聽器使用emitter.removeAllListener([event]) 。需要傳入某種類型的事件參數,不傳的話會把所有類型的事件監聽都移除掉。
demo:test4.js內容如下:
var http = require('http'); var server = http.createServer(); server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou,111'); console.log('shiyanlou,111'); res.end(); }); server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou,222'); console.log('shiyanlou,222'); res.end(); }); // 移除綁定的所有監聽器 server.removeAllListeners('request'); // 移除后再綁定一個有監聽器 server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou'); console.log('shiyanlou'); res.end(); }); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
瀏覽器只輸出shiyanlou
六、設置監聽器最大綁定數
EventEmitter支持多個事件監聽器,最大值是10。即可用為某個事件添加10個監聽函數,做10件事情。默認情況下,超過10個就好警告提示,
這能幫我們快速找到內存泄露的地方。
顯然,不是所有的事件觸發器都限制在10個監聽器,通過emitter.setMaxLisstener(n) 可以設置同一事件的監聽器最大綁定數,如果設置為0就是無限制。
七、自定義事件
使用emitter.emit(event,[arg1],[arg2],[...]) 可以觸發自定義的事件。
demo:test5.js內容如下
var http = require('http'); var server = http.createServer(); // 綁定自定義事件myevent server.on('myevent', function(arg) { console.log(arg); }); // 觸發自定義事件 server.emit('myevent', 'shiyanlou'); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/');
運行結果在console界面輸出shiyanlou,說明觸發自定義事件成功。
八、查看事件綁定的監聽器個數
使用EventEmitter.listenerCount(emitter,event) 可以查看事件監聽器數量。
也可以用emitter.listeners('event').length;來查看。
demo:test6.js內容如下
var http = require('http'); var events = require('events'); // 加載events模塊 var server = http.createServer(); server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou,111'); console.log('shiyanlou,111'); res.end(); }); server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou,222'); console.log('shiyanlou,222'); res.end(); }); server.listen(1337, '127.0.0.1'); console.log('Server running at http://127.0.0.1:1337/'); //2種方法 查看server綁定的'request'事件的監聽器個數 var num = events.EventEmitter.listenerCount(server, 'request'); var num2=server.listeners('request').length; console.log(num); console.log(num2);
2種方法運行結果都輸出了2,因為server綁定了兩個監聽器到"request"事件。
九、排錯
Error:write after end【update20170327】
server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou,111'); console.log('shiyanlou,111'); res.end(); }); server.on('request', function(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.write('shiyanlou,222'); console.log('shiyanlou,222'); res.end(); });
Once a writable stream is closed, it cannot accept anymore data。server綁定了2個request事件處理程序,第一個在res.write()后調用了res.end()結束了寫入流,所以再次調用res.write('shiyanlou,222');就會報錯,可以注釋掉第一end()調用。
本文作者starof,因知識本身在變化,作者也在不斷學習成長,文章內容也不定時更新,為避免誤導讀者,方便追根溯源,請諸位轉載注明出處:http://www.cnblogs.com/starof/p/5035522.html有問題歡迎與我討論,共同進步。
// 移除綁定的所有監聽器