時間或許能夠說是以JS來理解世界的基礎,針對於某一個狀況對象會作出何種反應,反應以後會作出何種處理,以及這一事件衍生出來了哪一些變化。node
大多數 Node.js 核心 API 都採用慣用的異步事件驅動架構,其中某些類型的對象(觸發器)會週期性地觸發命名事件來調用函數對象(監聽器)。數組
events模塊內容在引入的時候咱們獲取的將會是一個EventEmiter對象。EventEmiter對象內容是能夠綁定事件內容,或是觸發事件以達到相應的邏輯內容。下面先看一段代碼:架構
const ev = require('events');
class check extends ev {}
var checkT = new check();
checkT.on('change', function(){
console.dir(this);
})
checkT.emit('change');
console.log('');
checkT.on('change', function(){
console.dir(arguments);
})
checkT.emit('change');
console.log('');
checkT.prependListener('change', function(){
console.log('-----------------prependListener-------------');
});
checkT.emit('change');
由上面能夠看到咱們能夠經過extends的形式來拓展相關的類內容,使其繼承了EventEmitter類的特性,從而能夠綁定相關的事件內容。固然除了特定對象內容的事件能夠經過邏輯過程直接觸發以外,咱們本身定義的事件都是須要經過emit方法來進行觸發。異步
自動觸發的事件內容這裏能夠說明一下兩個特殊的事件那就是newListener和removeListener。當咱們對於EventEmitter類添加新的監聽以後會自動的觸發newListener這一事件,而當咱們刪除相關的監聽的時候會自動的觸發removeListener事件內容,咱們來嘗試一段代碼吧。函數
const ev = require('events');
class check extends ev {}
var checkT = new check();
checkT.on('newListener', function(){
console.log('Added new listener');
});
checkT.on('removeListener', function(){
console.log('Removed old listener');
});
var callback = function(){
return false;
}
checkT.on('check', callback);
checkT.removeListener('check', callback);
上圖對應的運行結果是:ui
下面咱們來一一介紹一下EventEmitter中提供的方法吧。this
--Event.Emitter.defaultMaxListeners:這是EventEmitter類的一個屬性,代表的是同一事件最多能夠綁定多少的回調函數。這是類級別屬性但它也是能夠設置的,可是並不推薦經過這一個方式來進行相關內容的設置,咱們能夠對於當前EventEmitter對象使用setMaxListeners()。spa
-- setMaxListener(n): 這一方法內容能夠用設置一個EventEmitter對象的默認的最大回調函數綁定個數,當超過這一個數的狀況之下nodeJS會爆出警告,超出範圍可能致使內存泄漏。線程
-- getMaxListener: 這一方法是用來獲取最大綁定事件個數的值的。3d
咱們來看一下代碼吧:
const ev = require('events');
class check extends ev {}
var checkT = new check();
console.log('當前類內容中的默認大小:'+ ev.defaultMaxListeners);
console.log('當前對象中的默認大小是:'+ checkT.getMaxListeners());
checkT.setMaxListeners(20);
console.log('當前類內容中的默認大小:'+ ev.defaultMaxListeners);
console.log('當前對象中的默認大小是:'+ checkT.getMaxListeners());
對應的結果以下:
-- eventNames:這一方法是返回了相應的數組內容,展現的是當前的對象已經綁定了哪一些事件類型或是符號。
-- listenerCount:這一方法傳遞參數事件類型或是相應的符號內容,而後返回當前的事件累心或者是符號對應的回調函數的個數。
-- listeners:傳遞的參數是事件類型內容,咱們獲取的對應的綁定事件數組內容。
上一段代碼內容:
const ev = require('events');
class check extends ev {}
var checkT = new check();
checkT.on('check', function(){});
var symbol = {check:'check'}
checkT.on(symbol, function(){});
console.dir(checkT.eventNames());
console.log('check事件綁定的回調個數:'+checkT.listenerCount('check'));
console.dir('check事件綁定的回調內容:'+checkT.listeners('check'));
相對應的結果:
-- on:第一個咱們固然要介紹一下on,事件綁定函數傳遞參數有兩,eventType(事件類型),callback(回調函數)另外還有一個別名叫作addListener。
-- once:綁定事件只執行一次,以後就再也不執行了。
-- prependListener:這一函數也是用來綁定事件的,可是其會將新添加的事件添加到事件隊列的頭部。事件隊列的內容會在以後說明。
-- prependOnceListener:相似於以前的once只是其將事件內容添加到事件隊列的頭部而已。
-- removeListener:相對應的咱們也有事件刪除操做,傳遞的參數內容是事件類型,和綁定的那一個callback函數內容。
-- removeAllListener:這是一個一勞永逸的方法,能夠傳遞一個事件類型或是標記的參數過去,而後會依據傳遞的參數,移除全部的對應這一參數的回調事件內容,固然若是不傳遞的話,則node會自動的將當前的對象中全部的事件所有刪除。
在看下一段代碼以前咱們來先說明一下事件隊列的內容,什麼是事件隊列。咱們知道咱們對於某一個對象的某一種事件類型或是標記能夠綁定多個回調函數,而這些回調函數之間是不會覆蓋彼此的,可是執行順序倒是成爲了讓人頭痛的事情,因此node使用了隊列來存儲相關的回調函數內容,會按照回調函數的添加前後順序進行相關內容的調用與觸發。而prepend開頭的函數則是將新增的事件回調邏輯添加到隊列頭部,則新加的事件內容會優先於以前的全部的添加內容執行。
下面來看一段代碼吧。
const ev = require('events');
class check extends ev {}
var checkT = new check();
checkT.on('check', function(){console.log('第一次添加的函數')});
checkT.once('check', function(){console.log('僅僅運行一次的函數')});
checkT.prependListener('check', function(){console.log('第三次添加的函數')});
checkT.prependOnceListener('check', function(){console.log('第四次添加的函數')});
checkT.emit('check');
console.log('--------------------------------------');
checkT.emit('check');
相應結果以下:
最後說明一下事件輪訓機制內容,事件輪訓實際上就是nodeJS的主要的事件運行思想,當運行相關內容的時候,node會會依照執行順序,當前可執行代碼排列到執行隊列之中,等待執行,而噹噹前的可執行隊列爲空的狀況之下,事件輪訓會自動的去檢查是否有任意代碼段從待執行狀態轉變成爲可執行狀態,這是再次的將可執行狀態的代碼段按照順序排列帶執行隊列之中,依次循環每次當執行隊列無代碼段的時候,事件輪訓就開始查詢。以此達到Node的單線程無阻斷形式的執行,也是NODE高效的緣由。