事件#

穩定性:2 - 穩定

原始碼: lib/events.js

許多 Node.js 核心 API 建立在慣用的非同步事件驅動架構上,在這種架構中,某些類型的物件(稱為「發射器」)會發出命名事件,導致呼叫 Function 物件(「監聽器」)。

例如:net.Server 物件會在每次對等端連線時發出事件;fs.ReadStream 會在開啟檔案時發出事件;串流 會在有資料可讀取時發出事件。

所有會發出事件的物件都是 EventEmitter 類別的執行個體。這些物件會公開一個 eventEmitter.on() 函式,允許將一個或多個函式附加到物件所發出的命名事件。通常,事件名稱會使用駝峰式大小寫字串,但任何有效的 JavaScript 屬性金鑰都可以使用。

EventEmitter 物件發出事件時,附加到該特定事件的所有函式都會同步呼叫。呼叫的監聽器所傳回的任何值都會被忽略並捨棄。

下列範例顯示一個具有單一監聽器的簡單 EventEmitter 執行個體。eventEmitter.on() 方法用於註冊監聽器,而 eventEmitter.emit() 方法用於觸發事件。

import { EventEmitter } from 'node:events';

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');const EventEmitter = require('node:events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

傳遞引數和 this 給監聽器#

eventEmitter.emit() 方法允許將一組任意的引數傳遞給監聽器函式。請記住,當呼叫一般監聽器函式時,標準 this 關鍵字會故意設定為參照附加監聽器的 EventEmitter 執行個體。

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // Prints:
  //   a b MyEmitter {
  //     _events: [Object: null prototype] { event: [Function (anonymous)] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined,
  //     [Symbol(shapeMode)]: false,
  //     [Symbol(kCapture)]: false
  //   } true
});
myEmitter.emit('event', 'a', 'b');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // Prints:
  //   a b MyEmitter {
  //     _events: [Object: null prototype] { event: [Function (anonymous)] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined,
  //     [Symbol(shapeMode)]: false,
  //     [Symbol(kCapture)]: false
  //   } true
});
myEmitter.emit('event', 'a', 'b');

可以將 ES6 箭頭函式用作監聽器,但是,這樣做時,this 關鍵字將不再參照 EventEmitter 執行個體。

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // Prints: a b undefined
});
myEmitter.emit('event', 'a', 'b');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');

非同步與同步#

EventEmitter 會依據註冊順序同步呼叫所有監聽器。這可確保事件的正確順序,並有助於避免競爭條件和邏輯錯誤。在適當的情況下,監聽器函式可以使用 setImmediate()process.nextTick() 方法切換到非同步操作模式

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  setImmediate(() => {
    console.log('this happens asynchronously');
  });
});
myEmitter.emit('event', 'a', 'b');const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  setImmediate(() => {
    console.log('this happens asynchronously');
  });
});
myEmitter.emit('event', 'a', 'b');

只處理事件一次#

當使用 eventEmitter.on() 方法註冊監聽器時,該監聽器會在每次發出指定事件時被呼叫

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2

使用 eventEmitter.once() 方法,可以註冊一個監聽器,該監聽器最多只會被呼叫一次以處理特定事件。一旦事件發出,監聽器就會被取消註冊,然後 才會被呼叫。

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignoredconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored

錯誤事件#

EventEmitter 執行個體內發生錯誤時,典型的動作是發出 'error' 事件。這些在 Node.js 中被視為特殊情況。

如果 EventEmitter 沒有 至少一個註冊的 'error' 事件監聽器,而 'error' 事件被發出,則會拋出錯誤、印出堆疊追蹤,且 Node.js 程序會結束。

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.jsconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js

為防止 Node.js 程序崩潰,可以使用 domain 模組。(但請注意,node:domain 模組已不建議使用。)

最佳實務是,應始終為 'error' 事件新增監聽器。

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an errorconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error

可以透過使用符號 events.errorMonitor 安裝監聽器,來監控 'error' 事件,而不會消耗發出的錯誤。

import { EventEmitter, errorMonitor } from 'node:events';

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
  MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.jsconst { EventEmitter, errorMonitor } = require('node:events');

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
  MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js

捕捉 Promise 的拒絕#

在事件處理常式中使用 async 函式是有問題的,因為在拋出例外情況時,可能會導致未處理的拒絕

import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
ee.on('something', async (value) => {
  throw new Error('kaboom');
});const EventEmitter = require('node:events');
const ee = new EventEmitter();
ee.on('something', async (value) => {
  throw new Error('kaboom');
});

EventEmitter 建構函式或全域設定中的 captureRejections 選項會變更此行為,在 Promise 上安裝一個 .then(undefined, handler) 處理常式。如果存在 Symbol.for('nodejs.rejection') 方法,此處理常式會非同步地將例外情況路由到該方法;如果不存在,則路由到 'error' 事件處理常式。

import { EventEmitter } from 'node:events';
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
  throw new Error('kaboom');
});

ee1.on('error', console.log);

const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
  throw new Error('kaboom');
});

ee2[Symbol.for('nodejs.rejection')] = console.log;const EventEmitter = require('node:events');
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
  throw new Error('kaboom');
});

ee1.on('error', console.log);

const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
  throw new Error('kaboom');
});

ee2[Symbol.for('nodejs.rejection')] = console.log;

設定 events.captureRejections = true 會變更所有新 EventEmitter 執行個體的預設值。

import { EventEmitter } from 'node:events';

EventEmitter.captureRejections = true;
const ee1 = new EventEmitter();
ee1.on('something', async (value) => {
  throw new Error('kaboom');
});

ee1.on('error', console.log);const events = require('node:events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
  throw new Error('kaboom');
});

ee1.on('error', console.log);

captureRejections 行為產生的 'error' 事件沒有 catch 處理常式,以避免無限錯誤迴圈:建議不要將 async 函式用作 'error' 事件處理常式

類別:EventEmitter#

EventEmitter 類別由 node:events 模組定義和公開

import { EventEmitter } from 'node:events';const EventEmitter = require('node:events');

所有 EventEmitter 都會在新增偵聽器時發出 'newListener' 事件,並在移除現有偵聽器時發出 'removeListener' 事件。

它支援下列選項

事件:'newListener'#

EventEmitter 實例會在偵聽器新增到其偵聽器內部陣列之前發出它自己的 'newListener' 事件。

'newListener' 事件註冊的偵聽器會傳遞事件名稱和對正在新增的偵聽器的參考。

事件在新增監聽器之前觸發,這會產生一個微妙但重要的副作用:任何在 'newListener' 回呼函數中註冊到同一個 name其他監聽器,會插入到正在新增的監聽器之前

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Insert a new listener in front
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Prints:
//   B
//   Aconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Insert a new listener in front
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Prints:
//   B
//   A

事件:'removeListener'#

'removeListener' 事件會在移除 listener 之後 觸發。

emitter.addListener(eventName, listener)#

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

emitter.emit(eventName[, ...args])#

同步呼叫已為命名為 eventName 的事件註冊的每個監聽器,按照它們的註冊順序,將提供的參數傳遞給每個監聽器。

如果事件有監聽器,則傳回 true,否則傳回 false

import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();

// First listener
myEmitter.on('event', function firstListener() {
  console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
  console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
  const parameters = args.join(', ');
  console.log(`event with parameters ${parameters} in third listener`);
});

console.log(myEmitter.listeners('event'));

myEmitter.emit('event', 1, 2, 3, 4, 5);

// Prints:
// [
//   [Function: firstListener],
//   [Function: secondListener],
//   [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listenerconst EventEmitter = require('node:events');
const myEmitter = new EventEmitter();

// First listener
myEmitter.on('event', function firstListener() {
  console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
  console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
  const parameters = args.join(', ');
  console.log(`event with parameters ${parameters} in third listener`);
});

console.log(myEmitter.listeners('event'));

myEmitter.emit('event', 1, 2, 3, 4, 5);

// Prints:
// [
//   [Function: firstListener],
//   [Function: secondListener],
//   [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener

emitter.eventNames()#

傳回一個陣列,列出已註冊監聽器的事件。陣列中的值是字串或 Symbol

import { EventEmitter } from 'node:events';

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

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

console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]const EventEmitter = require('node:events');

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

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

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

emitter.getMaxListeners()#

傳回 EventEmitter 的目前最大監聽器值,該值會由 emitter.setMaxListeners(n) 設定,或預設為 events.defaultMaxListeners

emitter.listenerCount(eventName[, listener])#

傳回監聽名為 eventName 事件的監聽器數量。如果提供 listener,它將傳回在事件監聽器清單中找到該監聽器的次數。

emitter.listeners(eventName)#

傳回名為 eventName 事件的監聽器陣列副本。

server.on('connection', (stream) => {
  console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ] 

emitter.off(eventName, listener)#

別名為 emitter.removeListener()

emitter.on(eventName, listener)#

listener 函式新增到名為 eventName 事件的監聽器陣列尾端。不會檢查 listener 是否已新增。多次呼叫傳遞相同的 eventNamelistener 組合,將會導致 listener 新增並呼叫多次。

server.on('connection', (stream) => {
  console.log('someone connected!');
}); 

傳回對 EventEmitter 的參考,以便呼叫可以串連。

預設情況下,事件監聽器會按新增順序呼叫。emitter.prependListener() 方法可以用作將事件監聽器新增到監聽器陣列開頭的替代方案。

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   aconst EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

emitter.once(eventName, listener)#

為名為 eventName 的事件新增一個一次性 listener 函式。下次觸發 eventName 時,此監聽器會被移除,然後呼叫。

server.once('connection', (stream) => {
  console.log('Ah, we have our first user!');
}); 

傳回對 EventEmitter 的參考,以便呼叫可以串連。

預設情況下,事件監聽器會按新增順序呼叫。emitter.prependOnceListener() 方法可以用作將事件監聽器新增到監聽器陣列開頭的替代方案。

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   aconst EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

emitter.prependListener(eventName, listener)#

listener 函式新增到名為 eventName 事件的 listeners 陣列開頭。不會檢查 listener 是否已新增。多次呼叫傳遞相同的 eventNamelistener 組合,將會導致 listener 被新增並呼叫多次。

server.prependListener('connection', (stream) => {
  console.log('someone connected!');
}); 

傳回對 EventEmitter 的參考,以便呼叫可以串連。

emitter.prependOnceListener(eventName, listener)#

eventName 事件的一次性 listener 函式新增到 listeners 陣列的開頭。下次觸發 eventName 時,此 listener 會被移除,然後呼叫。

server.prependOnceListener('connection', (stream) => {
  console.log('Ah, we have our first user!');
}); 

傳回對 EventEmitter 的參考,以便呼叫可以串連。

emitter.removeAllListeners([eventName])#

移除所有 listener,或移除指定 eventName 的 listener。

移除程式碼中其他位置新增的 listener 是不好的做法,特別是當 EventEmitter 執行個體是由其他元件或模組建立時(例如 socket 或檔案串流)。

傳回對 EventEmitter 的參考,以便呼叫可以串連。

emitter.removeListener(eventName, listener)#

從名為 eventName 事件的 listener 陣列中移除指定的 listener

const callback = (stream) => {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); 

removeListener() 最多會從 listener 陣列中移除 listener 的一個執行個體。如果任何單一 listener 已多次新增到指定 eventName 的 listener 陣列,則必須多次呼叫 removeListener() 才能移除每個執行個體。

一旦發出事件,所有在發出時附加到該事件的監聽器都會按順序被呼叫。這表示任何在發出之後和最後一個監聽器完成執行之前呼叫的 removeListener()removeAllListeners() 都無法從正在進行的 emit() 中移除它們。後續事件的行為符合預期。

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

const callbackA = () => {
  console.log('A');
  myEmitter.removeListener('event', callbackB);
};

const callbackB = () => {
  console.log('B');
};

myEmitter.on('event', callbackA);

myEmitter.on('event', callbackB);

// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
//   A
//   B

// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
//   Aconst EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

const callbackA = () => {
  console.log('A');
  myEmitter.removeListener('event', callbackB);
};

const callbackB = () => {
  console.log('B');
};

myEmitter.on('event', callbackA);

myEmitter.on('event', callbackB);

// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
//   A
//   B

// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
//   A

由於監聽器是使用內部陣列管理的,因此呼叫此方法會變更在移除監聽器之後註冊的任何監聽器的索引位置。這不會影響監聽器被呼叫的順序,但表示由 emitter.listeners() 方法傳回的任何監聽器陣列副本都需要重新建立。

當單一函式已多次新增為單一事件的處理常式(如下面的範例),removeListener() 會移除最近新增的執行個體。在範例中,once('ping') 監聽器會被移除

import { EventEmitter } from 'node:events';
const ee = new EventEmitter();

function pong() {
  console.log('pong');
}

ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);

ee.emit('ping');
ee.emit('ping');const EventEmitter = require('node:events');
const ee = new EventEmitter();

function pong() {
  console.log('pong');
}

ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);

ee.emit('ping');
ee.emit('ping');

傳回對 EventEmitter 的參考,以便呼叫可以串連。

emitter.setMaxListeners(n)#

預設情況下,如果為特定事件新增超過 10 個監聽器,EventEmitter 會列印警告。這是一個有用的預設值,有助於找出記憶體外洩。emitter.setMaxListeners() 方法允許修改此特定 EventEmitter 執行個體的限制。可以將值設定為 Infinity(或 0)以表示無限數量的監聽器。

傳回對 EventEmitter 的參考,以便呼叫可以串連。

emitter.rawListeners(eventName)#

傳回名為 eventName 的事件的監聽器陣列副本,包括任何包裝器(例如由 .once() 建立的包裝器)。

import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));

// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();

// Logs "log once" to the console and removes the listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');

// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));

// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();

// Logs "log once" to the console and removes the listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');

// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');

emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])#

如果在發出事件時發生承諾拒絕,且發出者已啟用 captureRejections,則會呼叫 Symbol.for('nodejs.rejection') 方法。可以使用 events.captureRejectionSymbol 取代 Symbol.for('nodejs.rejection')

import { EventEmitter, captureRejectionSymbol } from 'node:events';

class MyClass extends EventEmitter {
  constructor() {
    super({ captureRejections: true });
  }

  [captureRejectionSymbol](err, event, ...args) {
    console.log('rejection happened for', event, 'with', err, ...args);
    this.destroy(err);
  }

  destroy(err) {
    // Tear the resource down here.
  }
}const { EventEmitter, captureRejectionSymbol } = require('node:events');

class MyClass extends EventEmitter {
  constructor() {
    super({ captureRejections: true });
  }

  [captureRejectionSymbol](err, event, ...args) {
    console.log('rejection happened for', event, 'with', err, ...args);
    this.destroy(err);
  }

  destroy(err) {
    // Tear the resource down here.
  }
}

events.defaultMaxListeners#

預設情況下,最多可以為任何單一事件註冊 10 個監聽器。可以使用 emitter.setMaxListeners(n) 方法為個別的 EventEmitter 實例變更此限制。若要變更所有 EventEmitter 實例的預設值,可以使用 events.defaultMaxListeners 屬性。如果這個值不是正數,則會擲出 RangeError

設定 events.defaultMaxListeners 時請小心,因為變更會影響所有 EventEmitter 實例,包括在變更之前建立的實例。不過,呼叫 emitter.setMaxListeners(n) 仍然優先於 events.defaultMaxListeners

這不是硬性限制。EventEmitter 實例將允許新增更多監聽器,但會在 stderr 中輸出追蹤警告,指出已偵測到「可能的 EventEmitter 記憶體外洩」。對於任何單一的 EventEmitter,可以使用 emitter.getMaxListeners()emitter.setMaxListeners() 方法暫時避免此警告

import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
  // do stuff
  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
  // do stuff
  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});

可以使用 --trace-warnings 命令列旗標顯示此類警告的堆疊追蹤。

可以使用 process.on('warning') 檢查發出的警告,並且會具有額外的 emittertypecount 屬性,分別指涉事件發射器實例、事件名稱和附加的監聽器數量。其 name 屬性設定為 'MaxListenersExceededWarning'

events.errorMonitor#

此符號應僅用於安裝監聽器以監控 'error' 事件。使用此符號安裝的監聽器會在呼叫一般 'error' 監聽器之前呼叫。

使用此符號安裝監聽器不會在發出 'error' 事件後變更行為。因此,如果未安裝任何一般 'error' 監聽器,程序仍然會崩潰。

events.getEventListeners(emitterOrTarget, eventName)#

傳回名為 eventName 事件的監聽器陣列副本。

對於 EventEmitter,這與在發射器上呼叫 .listeners 的行為完全相同。

對於 EventTarget,這是取得事件目標的事件監聽器的唯一方法。這對於偵錯和診斷目的很有用。

import { getEventListeners, EventEmitter } from 'node:events';

{
  const ee = new EventEmitter();
  const listener = () => console.log('Events are fun');
  ee.on('foo', listener);
  console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
  const et = new EventTarget();
  const listener = () => console.log('Events are fun');
  et.addEventListener('foo', listener);
  console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}const { getEventListeners, EventEmitter } = require('node:events');

{
  const ee = new EventEmitter();
  const listener = () => console.log('Events are fun');
  ee.on('foo', listener);
  console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
  const et = new EventTarget();
  const listener = () => console.log('Events are fun');
  et.addEventListener('foo', listener);
  console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}

events.getMaxListeners(emitterOrTarget)#

傳回目前設定的監聽器最大數量。

對於 EventEmitter,這與在發射器上呼叫 .getMaxListeners 的行為完全相同。

對於 EventTarget,這是取得事件目標的最大事件監聽器的唯一方法。如果單一 EventTarget 上的事件處理常式數量超過設定的最大值,EventTarget 會印出警告。

import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';

{
  const ee = new EventEmitter();
  console.log(getMaxListeners(ee)); // 10
  setMaxListeners(11, ee);
  console.log(getMaxListeners(ee)); // 11
}
{
  const et = new EventTarget();
  console.log(getMaxListeners(et)); // 10
  setMaxListeners(11, et);
  console.log(getMaxListeners(et)); // 11
}const { getMaxListeners, setMaxListeners, EventEmitter } = require('node:events');

{
  const ee = new EventEmitter();
  console.log(getMaxListeners(ee)); // 10
  setMaxListeners(11, ee);
  console.log(getMaxListeners(ee)); // 11
}
{
  const et = new EventTarget();
  console.log(getMaxListeners(et)); // 10
  setMaxListeners(11, et);
  console.log(getMaxListeners(et)); // 11
}

events.once(emitter, name[, options])#

建立一個Promise,當EventEmitter發出指定的事件時,會達成此Promise,或者在等待時,EventEmitter發出'error'時,會拒絕此PromisePromise會解析為發出至指定事件的所有參數陣列。

此方法故意設計成通用的,並與網路平台EventTarget介面一起使用,此介面沒有特殊的'error'事件語意,也不會偵聽'error'事件。

import { once, EventEmitter } from 'node:events';
import process from 'node:process';

const ee = new EventEmitter();

process.nextTick(() => {
  ee.emit('myevent', 42);
});

const [value] = await once(ee, 'myevent');
console.log(value);

const err = new Error('kaboom');
process.nextTick(() => {
  ee.emit('error', err);
});

try {
  await once(ee, 'myevent');
} catch (err) {
  console.error('error happened', err);
}const { once, EventEmitter } = require('node:events');

async function run() {
  const ee = new EventEmitter();

  process.nextTick(() => {
    ee.emit('myevent', 42);
  });

  const [value] = await once(ee, 'myevent');
  console.log(value);

  const err = new Error('kaboom');
  process.nextTick(() => {
    ee.emit('error', err);
  });

  try {
    await once(ee, 'myevent');
  } catch (err) {
    console.error('error happened', err);
  }
}

run();

只有在使用events.once()等待另一個事件時,才會特別處理'error'事件。如果使用events.once()等待'error'事件本身,則會將其視為任何其他類型的事件,而不會特別處理

import { EventEmitter, once } from 'node:events';

const ee = new EventEmitter();

once(ee, 'error')
  .then(([err]) => console.log('ok', err.message))
  .catch((err) => console.error('error', err.message));

ee.emit('error', new Error('boom'));

// Prints: ok boomconst { EventEmitter, once } = require('node:events');

const ee = new EventEmitter();

once(ee, 'error')
  .then(([err]) => console.log('ok', err.message))
  .catch((err) => console.error('error', err.message));

ee.emit('error', new Error('boom'));

// Prints: ok boom

可以使用<AbortSignal>取消等待事件

import { EventEmitter, once } from 'node:events';

const ee = new EventEmitter();
const ac = new AbortController();

async function foo(emitter, event, signal) {
  try {
    await once(emitter, event, { signal });
    console.log('event emitted!');
  } catch (error) {
    if (error.name === 'AbortError') {
      console.error('Waiting for the event was canceled!');
    } else {
      console.error('There was an error', error.message);
    }
  }
}

foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!const { EventEmitter, once } = require('node:events');

const ee = new EventEmitter();
const ac = new AbortController();

async function foo(emitter, event, signal) {
  try {
    await once(emitter, event, { signal });
    console.log('event emitted!');
  } catch (error) {
    if (error.name === 'AbortError') {
      console.error('Waiting for the event was canceled!');
    } else {
      console.error('There was an error', error.message);
    }
  }
}

foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!

等待在process.nextTick()上發出的多個事件#

在使用events.once()函式等待在同一批次process.nextTick()作業中發出的多個事件,或每當多個事件同步發出時,有一個值得注意的邊界情況。特別是,因為process.nextTick()佇列會在Promise微任務佇列之前耗盡,而且因為EventEmitter會同步發出所有事件,因此events.once()可能會錯過一個事件。

import { EventEmitter, once } from 'node:events';
import process from 'node:process';

const myEE = new EventEmitter();

async function foo() {
  await once(myEE, 'bar');
  console.log('bar');

  // This Promise will never resolve because the 'foo' event will
  // have already been emitted before the Promise is created.
  await once(myEE, 'foo');
  console.log('foo');
}

process.nextTick(() => {
  myEE.emit('bar');
  myEE.emit('foo');
});

foo().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');

const myEE = new EventEmitter();

async function foo() {
  await once(myEE, 'bar');
  console.log('bar');

  // This Promise will never resolve because the 'foo' event will
  // have already been emitted before the Promise is created.
  await once(myEE, 'foo');
  console.log('foo');
}

process.nextTick(() => {
  myEE.emit('bar');
  myEE.emit('foo');
});

foo().then(() => console.log('done'));

若要捕捉兩個事件,請在等待其中任何一個事件之前建立每個Promise,然後就可以使用Promise.all()Promise.race()Promise.allSettled()

import { EventEmitter, once } from 'node:events';
import process from 'node:process';

const myEE = new EventEmitter();

async function foo() {
  await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
  console.log('foo', 'bar');
}

process.nextTick(() => {
  myEE.emit('bar');
  myEE.emit('foo');
});

foo().then(() => console.log('done'));const { EventEmitter, once } = require('node:events');

const myEE = new EventEmitter();

async function foo() {
  await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
  console.log('foo', 'bar');
}

process.nextTick(() => {
  myEE.emit('bar');
  myEE.emit('foo');
});

foo().then(() => console.log('done'));

events.captureRejections#

值:<布林值>

變更所有新的 EventEmitter 物件上預設的 captureRejections 選項。

events.captureRejectionSymbol#

值:Symbol.for('nodejs.rejection')

查看如何撰寫自訂 rejection 處理常式

events.listenerCount(emitter, eventName)#

穩定性:0 - 已棄用:改用 emitter.listenerCount()

傳回在給定 emitter 上註冊的給定 eventName 的監聽器數量的類別方法。

import { EventEmitter, listenerCount } from 'node:events';

const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2const { EventEmitter, listenerCount } = require('node:events');

const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2

events.on(emitter, eventName[, options])#

import { on, EventEmitter } from 'node:events';
import process from 'node:process';

const ee = new EventEmitter();

// Emit later on
process.nextTick(() => {
  ee.emit('foo', 'bar');
  ee.emit('foo', 42);
});

for await (const event of on(ee, 'foo')) {
  // The execution of this inner block is synchronous and it
  // processes one event at a time (even with await). Do not use
  // if concurrent execution is required.
  console.log(event); // prints ['bar'] [42]
}
// Unreachable hereconst { on, EventEmitter } = require('node:events');

(async () => {
  const ee = new EventEmitter();

  // Emit later on
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo')) {
    // The execution of this inner block is synchronous and it
    // processes one event at a time (even with await). Do not use
    // if concurrent execution is required.
    console.log(event); // prints ['bar'] [42]
  }
  // Unreachable here
})();

傳回反覆處理 eventName 事件的 非同步迭代器。如果 EventEmitter 發出 'error',它會擲回錯誤。在離開迴圈時,它會移除所有監聽器。每個反覆處理傳回的 value 都是一個陣列,由發出的事件引數組成。

<AbortSignal> 可用於取消等待事件

import { on, EventEmitter } from 'node:events';
import process from 'node:process';

const ac = new AbortController();

(async () => {
  const ee = new EventEmitter();

  // Emit later on
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo', { signal: ac.signal })) {
    // The execution of this inner block is synchronous and it
    // processes one event at a time (even with await). Do not use
    // if concurrent execution is required.
    console.log(event); // prints ['bar'] [42]
  }
  // Unreachable here
})();

process.nextTick(() => ac.abort());const { on, EventEmitter } = require('node:events');

const ac = new AbortController();

(async () => {
  const ee = new EventEmitter();

  // Emit later on
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo', { signal: ac.signal })) {
    // The execution of this inner block is synchronous and it
    // processes one event at a time (even with await). Do not use
    // if concurrent execution is required.
    console.log(event); // prints ['bar'] [42]
  }
  // Unreachable here
})();

process.nextTick(() => ac.abort());

events.setMaxListeners(n[, ...eventTargets])#

import { setMaxListeners, EventEmitter } from 'node:events';

const target = new EventTarget();
const emitter = new EventEmitter();

setMaxListeners(5, target, emitter);const {
  setMaxListeners,
  EventEmitter,
} = require('node:events');

const target = new EventTarget();
const emitter = new EventEmitter();

setMaxListeners(5, target, emitter);

events.addAbortListener(signal, listener)#

穩定性:1 - 實驗性

在提供的 signal 上監聽 abort 事件一次。

監聽 abort 訊號上的 abort 事件並不安全,而且可能會導致資源外洩,因為具有訊號的另一個第三方可以呼叫 e.stopImmediatePropagation()。很不幸地,Node.js 無法變更這一點,因為這會違反網路標準。此外,原始 API 很容易讓人忘記移除監聽器。

這個 API 允許在 Node.js API 中安全地使用 AbortSignal,方法是解決這兩個問題,透過監聽事件,讓 stopImmediatePropagation 無法阻止監聽器執行。

傳回一個 disposable,以便可以更容易地取消訂閱。

const { addAbortListener } = require('node:events');

function example(signal) {
  let disposable;
  try {
    signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
    disposable = addAbortListener(signal, (e) => {
      // Do something when signal is aborted.
    });
  } finally {
    disposable?.[Symbol.dispose]();
  }
}import { addAbortListener } from 'node:events';

function example(signal) {
  let disposable;
  try {
    signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
    disposable = addAbortListener(signal, (e) => {
      // Do something when signal is aborted.
    });
  } finally {
    disposable?.[Symbol.dispose]();
  }
}

類別:events.EventEmitterAsyncResource extends EventEmitter#

EventEmitter<AsyncResource> 整合,以供需要手動非同步追蹤的 EventEmitter。特別是,由 events.EventEmitterAsyncResource 執行個體發出的所有事件都將在其 非同步內容 中執行。

import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
import { notStrictEqual, strictEqual } from 'node:assert';
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';

// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });

// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
  strictEqual(executionAsyncId(), ee1.asyncId);
  strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});

const ee2 = new EventEmitter();

// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
  notStrictEqual(executionAsyncId(), ee2.asyncId);
  notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});

Promise.resolve().then(() => {
  ee1.emit('foo');
  ee2.emit('foo');
});const { EventEmitterAsyncResource, EventEmitter } = require('node:events');
const { notStrictEqual, strictEqual } = require('node:assert');
const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');

// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });

// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
  strictEqual(executionAsyncId(), ee1.asyncId);
  strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});

const ee2 = new EventEmitter();

// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
  notStrictEqual(executionAsyncId(), ee2.asyncId);
  notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});

Promise.resolve().then(() => {
  ee1.emit('foo');
  ee2.emit('foo');
});

EventEmitterAsyncResource 類別具有與 EventEmitterAsyncResource 本身相同的 method,並採用相同的選項。

new events.EventEmitterAsyncResource([options])#

  • options <Object>
    • captureRejections <boolean> 它啟用 自動擷取 Promise 拒絕預設值:false
    • name <字串> 非同步事件的類型。預設: new.target.name
    • triggerAsyncId <數字> 建立此非同步事件的執行內容 ID。預設: executionAsyncId()
    • requireManualDestroy <布林> 如果設為 true,當物件被垃圾回收時,會停用 emitDestroy。通常不需要設定(即使 emitDestroy 手動呼叫),除非資源的 asyncId 已擷取,且敏感 API 的 emitDestroy 已使用它呼叫。如果設為 false,只有在至少有一個 active destroy 掛勾時,垃圾回收的 emitDestroy 呼叫才會發生。預設: false

eventemitterasyncresource.asyncId#

  • 類型:<數字> 指派給資源的唯一 asyncId

eventemitterasyncresource.asyncResource#

傳回的 AsyncResource 物件具有額外的 eventEmitter 屬性,提供對此 EventEmitterAsyncResource 的參考。

eventemitterasyncresource.emitDestroy()#

呼叫所有 destroy 掛勾。這只應呼叫一次。如果呼叫超過一次,將會擲回錯誤。這必須手動呼叫。如果資源留待 GC 收集,則 destroy 掛勾將永遠不會被呼叫。

eventemitterasyncresource.triggerAsyncId#

  • 類型:<number> 傳遞給 AsyncResource 建構函式的 triggerAsyncId

EventTargetEvent API#

EventTargetEvent 物件是 EventTarget Web API 的 Node.js 特定實作,由一些 Node.js 核心 API 公開。

const target = new EventTarget();

target.addEventListener('foo', (event) => {
  console.log('foo event happened!');
}); 

Node.js EventTarget 與 DOM EventTarget#

Node.js EventTargetEventTarget Web API 之間有兩個主要差異

  1. DOM EventTarget 執行個體可能會是階層式的,但在 Node.js 中沒有階層和事件傳播的概念。也就是說,傳送至 EventTarget 的事件不會透過嵌套目標物件的階層傳播,而每個目標物件可能都有自己的一組事件處理常式。
  2. 在 Node.js EventTarget 中,如果事件監聽器是非同步函式或傳回 Promise,且傳回的 Promise 遭拒絕,則會自動擷取拒絕並以與同步擲回例外狀況的監聽器相同的方式處理(詳情請參閱 EventTarget 錯誤處理)。

NodeEventTargetEventEmitter#

NodeEventTarget 物件實作了 EventEmitter API 的修改子集,讓它能在特定情況下嚴密模擬EventEmitterNodeEventTarget 不是EventEmitter 的執行個體,且在多數情況下無法取代 EventEmitter

  1. EventEmitter 不同,任何給定的 listener 每個事件 type 最多只能註冊一次。嘗試多次註冊 listener 會被忽略。
  2. NodeEventTarget 沒有模擬完整的 EventEmitter API。特別是 prependListener()prependOnceListener()rawListeners()errorMonitor API 沒有被模擬。'newListener''removeListener' 事件也不會被發射。
  3. NodeEventTarget 沒有實作任何 'error' 類型的事件的特殊預設行為。
  4. NodeEventTarget 支援 EventListener 物件以及函式作為所有事件類型的處理常式。

事件聆聽器#

為事件 type 註冊的事件聆聽器可以是 JavaScript 函式或具有 handleEvent 屬性的物件,其值為函式。

在任何情況下,處理常式函式都會使用傳遞給 eventTarget.dispatchEvent() 函式的 event 引數來呼叫。

非同步函式可以用作事件聆聽器。如果非同步處理常式函式被拒絕,拒絕會被捕捉並處理,如 EventTarget 錯誤處理 中所述。

一個處理常式函式拋出的錯誤不會阻止其他處理常式被呼叫。

處理常式函式的傳回值會被忽略。

處理常式總是按照加入的順序被呼叫。

處理常式函式可以變異 event 物件。

function handler1(event) {
  console.log(event.type);  // Prints 'foo'
  event.a = 1;
}

async function handler2(event) {
  console.log(event.type);  // Prints 'foo'
  console.log(event.a);  // Prints 1
}

const handler3 = {
  handleEvent(event) {
    console.log(event.type);  // Prints 'foo'
  },
};

const handler4 = {
  async handleEvent(event) {
    console.log(event.type);  // Prints 'foo'
  },
};

const target = new EventTarget();

target.addEventListener('foo', handler1);
target.addEventListener('foo', handler2);
target.addEventListener('foo', handler3);
target.addEventListener('foo', handler4, { once: true }); 

EventTarget 錯誤處理#

當註冊的事件監聽器擲回(或傳回一個會拒絕的 Promise)時,預設會將錯誤視為 `process.nextTick()` 上的未捕捉例外。這表示 `EventTarget` 中的未捕捉例外會預設終止 Node.js 程序。

在事件監聽器中擲回不會停止呼叫其他註冊的處理常式。

`EventTarget` 沒有實作任何針對 `'error'` 類型事件的特殊預設處理,例如 `EventEmitter`。

目前錯誤會先轉送至 `process.on('error')` 事件,才會到達 `process.on('uncaughtException')`。此行為已不建議使用,且會在未來的版本中變更,以使 `EventTarget` 與其他 Node.js API 保持一致。任何依賴 `process.on('error')` 事件的程式碼都應與新行為保持一致。

類別:Event#

`Event` 物件是 Event Web API 的改編版本。執行個體是由 Node.js 內部建立。

event.bubbles#

這在 Node.js 中並未使用,純粹為了完整性而提供。

event.cancelBubble#

穩定性:3 - 已不建議使用:請改用 event.stopPropagation()

如果設為 true,則為 event.stopPropagation() 的別名。這在 Node.js 中未使用,純粹為了完整性而提供。

event.cancelable#
  • 類型:<布林值> 如果事件是用 cancelable 選項建立的,則為 True。
event.composed#

這在 Node.js 中並未使用,純粹為了完整性而提供。

event.composedPath()#

傳回一個陣列,包含目前的 EventTarget 作為唯一的項目,如果事件未被發送,則為空。這在 Node.js 中未使用,純粹為了完整性而提供。

event.currentTarget#

event.target 的別名。

event.defaultPrevented#

如果 cancelabletrue 且已呼叫 event.preventDefault(),則為 true

event.eventPhase#
  • 類型:<數字> 在事件未被發送時傳回 0,在事件被發送時傳回 2

這在 Node.js 中並未使用,純粹為了完整性而提供。

event.initEvent(type[, bubbles[, cancelable]])#

穩定性:3 - 傳統:WHATWG 規格視其為不建議使用,使用者不應使用。

與事件建構函式重複,且無法設定 composed。這在 Node.js 中未使用,僅為完整性而提供。

event.isTrusted#

<中斷訊號> "中斷" 事件會在 isTrusted 設為 true 的情況下發出。在所有其他情況下,其值為 false

event.preventDefault()#

如果 cancelabletrue,則將 defaultPrevented 屬性設為 true

event.returnValue#

  • 類型:<布林> 如果事件尚未取消,則為 True。

event.returnValue 的值永遠與 event.defaultPrevented 相反。這在 Node.js 中未使用,僅為完整性而提供。

event.srcElement#

穩定性:3 - 傳統:改用 event.target

event.target 的別名。

event.stopImmediatePropagation()#

在目前事件完成後停止呼叫事件監聽器。

event.stopPropagation()#

這在 Node.js 中並未使用,純粹為了完整性而提供。

event.target#
event.timeStamp#

建立 Event 物件時的毫秒時間戳記。

event.type#

事件類型識別碼。

類別:EventTarget#

eventTarget.addEventListener(type, listener[, options])#
  • type <字串>
  • listener <Function> | <EventListener>
  • options <Object>
    • once <boolean> 若為 true,則在第一次呼叫時自動移除監聽器。預設值:false
    • passive <boolean> 若為 true,則表示監聽器不會呼叫 Event 物件的 preventDefault() 方法。預設值:false
    • capture <boolean> Node.js 未直接使用。為 API 完整性而新增。預設值:false
    • signal <AbortSignal> 當呼叫所提供 AbortSignal 物件的 abort() 方法時,將移除監聽器。

type 事件新增新的處理常式。任何指定的 listener 僅會針對每個 type 和每個 capture 選項值新增一次。

如果 once 選項為 true,則在下次派送 type 事件後,將移除 listener

capture 選項不會以任何功能性的方式被 Node.js 使用,只會根據 EventTarget 規格追蹤已註冊的事件監聽器。具體來說,capture 選項在註冊 listener 時用作金鑰的一部分。任何個別的 listener 都可以新增一次,其中 capture = false,並新增一次,其中 capture = true

function handler(event) {}

const target = new EventTarget();
target.addEventListener('foo', handler, { capture: true });  // first
target.addEventListener('foo', handler, { capture: false }); // second

// Removes the second instance of handler
target.removeEventListener('foo', handler);

// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true }); 
eventTarget.dispatchEvent(event)#
  • event <Event>
  • 傳回:<boolean> 如果事件的 cancelable 屬性值為 false 或未呼叫其 preventDefault() 方法,則為 true,否則為 false

event 派送至 event.type 的處理常式清單。

已註冊的事件監聽器會以註冊順序同步呼叫。

eventTarget.removeEventListener(type, listener[, options])#

從事件 type 的處理常式清單中移除 listener

類別:CustomEvent#

穩定性:1 - 實驗性。

CustomEvent 物件是 CustomEvent Web API 的改編。執行個體由 Node.js 內部建立。

event.detail#

穩定性:1 - 實驗性。

  • 類型:<any> 傳回初始化時傳遞的自訂資料。

唯讀。

類別:NodeEventTarget#

NodeEventTargetEventTarget 的 Node.js 特定延伸,模擬 EventEmitter API 的子集。

nodeEventTarget.addListener(type, listener)#

EventTarget 類別的 Node.js 特定延伸,模擬等效的 EventEmitter API。addListener()addEventListener() 之間唯一的差異在於 addListener() 會傳回對 EventTarget 的參考。

nodeEventTarget.emit(type, arg)#
  • type <字串>
  • arg <any>
  • 傳回:<boolean> 如果已註冊 type 的事件聆聽器,則為 true,否則為 false

EventTarget 類別的 Node.js 特定延伸,將 arg 傳送給 type 的處理常式清單。

nodeEventTarget.eventNames()#

EventTarget 類別的 Node.js 特定延伸,傳回已註冊事件聆聽器的事件 type 名稱陣列。

nodeEventTarget.listenerCount(type)#

EventTarget 類別的 Node.js 特定延伸,傳回已註冊 type 的事件聆聽器數量。

nodeEventTarget.setMaxListeners(n)#

Node.js 特有的擴充套件,用於將最大事件監聽器數量設定為 nEventTarget 類別。

nodeEventTarget.getMaxListeners()#

Node.js 特有的擴充套件,用於傳回最大事件監聽器數量,用於 EventTarget 類別。

nodeEventTarget.off(type, listener[, options])#

eventTarget.removeEventListener() 的 Node.js 特有別名。

nodeEventTarget.on(type, listener)#

eventTarget.addEventListener() 的 Node.js 特有別名。

nodeEventTarget.once(type, listener)#

Node.js 特有的擴充套件,用於針對指定的事件 type 新增 once 監聽器。這等於呼叫 on,並將 once 選項設定為 true

nodeEventTarget.removeAllListeners([type])#

Node.js 特有的擴充套件,用於 EventTarget 類別。如果指定 type,則移除所有已註冊的 type 監聽器,否則移除所有已註冊的監聽器。

nodeEventTarget.removeListener(type, listener[, options])#

EventTarget 類別的 Node.js 專屬擴充功能,用於移除給定 typelistenerremoveListener()removeEventListener() 之間唯一的差異是 removeListener() 會傳回對 EventTarget 的參考。