【每日一包0025】events

[github地址:https://github.com/ABCDdouyae...]git

events

事件觸發器

大多數 Node.js 核心 API 構建於慣用的異步事件驅動架構,其中某些類型的對象(又稱觸發器,Emitter)會觸發命名事件來調用函數(又稱監聽器,Listener)。全部能觸發事件的對象都是 EventEmitter 類的實例。 這些對象有一個 eventEmitter.on() 函數,用於將一個或多個函數綁定到命名事件上。 事件的命名一般是駝峯式的字符串。當 EventEmitter 對象觸發一個事件時,全部綁定在該事件上的函數都會被同步地調用

基本用法:實例化一個監聽器,註冊監聽事件‘event’,當經過emit觸發‘event’時候,會調用回調函數github

const EventEmitter = require('events');

class MyEmitter extends EventEmitter{}

const myEmitter = new MyEmitter();
myEmitter.on('event', ()=>{
    console.log('觸發事件')
});

myEmitter.emit('event');

eventEmitter.emit() 方法能夠傳任意數量的參數到監聽器函數。 當監聽器函數被調用時,this 關鍵詞會被指向監聽器所綁定的 EventEmitter 實例。

myEmitter.on('event1', function(a ,b){
    console.log(a, b, this)//1 2 MyEmitter{}
});

myEmitter.emit('event1', 1, 2);

也可使用 ES6 的箭頭函數做爲監聽器。但 this 關鍵詞不會指向 EventEmitter 實例:數組

myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // 打印: a b {}
});
myEmitter.emit('event', 'a', 'b');

使用 eventEmitter.once() 能夠註冊最多可調用一次的監聽器。 當事件被觸發時,監聽器會被註銷,而後再調用。

let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// 打印: 1
myEmitter.emit('event');
// 不觸發

當 EventEmitter 實例出錯時,應該觸發 'error' 事件。若是沒有爲 'error' 事件註冊監聽器,則當 'error' 事件觸發時,會拋出錯誤、打印堆棧跟蹤、並退出 Node.js 進程

myEmitter.emit('error', new Error('錯誤信息'));
// 拋出錯誤

做爲最佳實踐,應該始終爲 'error' 事件註冊監聽器。架構

myEmitter.on('error', (err) => {
  console.error('錯誤信息');
});
myEmitter.emit('error', new Error('錯誤信息'));
// 打印: 錯誤信息

EventEmitter 類由 events 模塊定義:

const EventEmitter = require('events');

當新增監聽器時,會觸發 'newListener' 事件;當移除已存在的監聽器時,則觸發 'removeListener' 事件。app

newListener的參數分別爲增長的監聽事件和該事件的句柄函數異步

myEmitter.once('newListener', (event, listener)=>{
    console.log(event, listener)// 'event1' fn
});

function fn(){
    console.log(1)
}
myEmitter.on('event1', fn)

在添加監聽器以前觸發 'newListener' 事件有一個反作用: 若是在回調中註冊同名事件的監聽器,則該監聽器會被插入到正被添加的監聽器前面。函數

const myEmitter = new MyEmitter();
// 只處理一次,避免無限循環。
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // 在前面插入一個新的監聽器。
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// 打印:
//   B
//   A

removeListener的參數分別爲移除的監聽事件和該事件的句柄函數ui

EventEmitter.defaultMaxListeners默認狀況下,每一個事件能夠註冊最多 10 個監聽器。 可使用 emitter.setMaxListeners(n) 方法改變單個 EventEmitter 實例的限制。 可使用 EventEmitter.defaultMaxListeners 屬性改變全部 EventEmitter 實例的默認值。設置 EventEmitter.defaultMaxListeners 要謹慎,由於會影響全部 EventEmitter 實例,包括以前建立的。 於是,優先使用 emitter.setMaxListeners(n) 而不是 `EventEmitter.defaultMaxListeners。限制不是硬性的。 EventEmitter 實例能夠添加超過限制的監聽器,但會向 stderr 輸出跟蹤警告,代表檢測到可能的內存泄漏。 對於單個 EventEmitter 實例,可使用 emitter.getMaxListeners()emitter.setMaxListeners() 暫時地消除警告

console.log(myEmitter.getMaxListeners())//10
myEmitter.setMaxListeners(11);
function fn(){
    console.log(1)//11個1
}
for(var i=0;i<11;i++){
    myEmitter.on('event1', fn)
}

myEmitter.emit('event1')

emitter.addListener(eventName, listener), emitter.on(eventName, listener)的別名

emitter.emit(eventName[, ...args])按照監聽器註冊的順序,同步地調用每一個註冊到名爲 eventName 的事件的監聽器,並傳入提供的參數。若是事件有監聽器,則返回 true,不然返回 false。

emitter.eventNames() 返回已註冊監聽器的事件名數組。 數組中的值爲字符串或 `Symbol。

const EventEmitter = require('events');
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});

const sym = Symbol('symbol');
myEE.on(sym, () => {});

console.log(myEE.eventNames());
// 打印: [ 'foo', 'bar', Symbol(symbol) ]

emitter.getMaxListeners()返回 EventEmitter 當前的監聽器最大限制數的值

emitter.listenerCount(eventName)返回正在監聽的名爲 eventName 的事件的監聽器的數量。

emitter.listeners(eventName)返回名爲 eventName 的事件的監聽器數組的副本。

let fn1 = ()=>{}, fn2 = ()=>{};
myEmitter.on('foo', fn1);
myEmitter.on('foo', fn2);
console.log(myEmitter.listeners('foo'));
//[ [Function: fn1], [Function: fn2] ]

emitter.off(eventName, listener), emitter.removeListener() 的別名。

emitter.prependListener(eventName, listener)添加 listener 函數到名爲 eventName 的事件的監聽器數組的開頭。 不會檢查 listener 是否已被添加。 屢次調用並傳入相同的 eventName 和 listener 會致使 listener 被添加屢次。

emitter.prependOnceListener(eventName, listener)添加單次監聽器 listener 到名爲 eventName 的事件的監聽器數組的開頭。 當 eventName 事件下次觸發時,監聽器會先被移除,而後再調用。

emitter.removeAllListeners([eventName])移除所有監聽器或指定的 eventName 事件的監聽器。

emitter.removeListener(eventName, listener)從名爲 eventName 的事件的監聽器數組中移除指定的 listener。

let fn1 = ()=>{console.log(1)}, fn2 = ()=>{console.log(2)};//2
myEmitter.on('foo', fn1);
myEmitter.on('foo', fn2);
console.log(myEmitter.listeners('foo'));
//[ [Function: fn1], [Function: fn2] ]

myEmitter.off('foo', fn1);
myEmitter.emit('foo');

emitter.setMaxListeners(n)默認狀況下,若是爲特定事件添加了超過 10 個監聽器,則 EventEmitter 會打印一個警告。 這有助於發現內存泄露。 可是,並非全部的事件都要限制 10 個監聽器。 emitter.setMaxListeners() 方法能夠爲指定的 EventEmitter 實例修改限制。 值設爲 Infinity(或 0)表示不限制監聽器的數量。

emitter.rawListeners(eventName)返回 eventName 事件的監聽器數組的拷貝,包括封裝的監聽器(例如由 .once() 建立的)。

const emitter = new EventEmitter();
emitter.once('log', () => console.log('只記錄一次'));

// 返回一個數組,包含了一個封裝了 `listener` 方法的監聽器。
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// 打印 「只記錄一次」,但不會解綁 `once` 事件。
logFnWrapper.listener();

// 打印 「只記錄一次」,且移除監聽器。
logFnWrapper();

emitter.on('log', () => console.log('持續地記錄'));
// 返回一個數組,只包含 `.on()` 綁定的監聽器。
const newListeners = emitter.rawListeners('log');

// 打印兩次 「持續地記錄」。
newListeners[0]();
emitter.emit('log');
相關文章
相關標籤/搜索