事件#

穩定度:2 - 穩定

許多 Node.js 核心 API 都是圍繞著慣用的非同步事件驅動架構建構的,在這種架構中,某些物件(稱為「發送器」,emitters)會發送具名事件,導致 Function 物件(「監聽器」,listeners)被呼叫。

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

所有發送事件的物件都是 EventEmitter 類別的實例。這些物件公開了 eventEmitter.on() 函式,允許將一個或多個函式附加到物件發送的具名事件上。通常,事件名稱是小駝峰式 (camel-cased) 字串,但也可以使用任何有效的 JavaScript 屬性鍵值 (property key)。

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 會按照監聽器註冊的順序同步呼叫所有監聽器。這確保了事件的正確順序,並有助於避免競爭條件 (race conditions) 和邏輯錯誤。在適當的時候,監聽器函式可以使用 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: 2
const 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');
// Ignored
const 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.js
const 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 error
const 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.js
const { 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 的拒絕 (rejections)#

在事件處理程式中使用 async 函式是有問題的,因為如果拋出異常,可能會導致未處理的拒絕 (unhandled rejection)。

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
//   A
const 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 listener
const 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()#

傳回一個陣列,列出發送器已註冊監聽器的事件。

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
//   a
const 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
//   a
const 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 事件的監聽器陣列的開頭。不會檢查 listener 是否已添加。多次傳遞相同的 eventNamelistener 組合呼叫將導致 listener 被多次添加和呼叫。

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

傳回對 EventEmitter 的參考,以便可以鏈式呼叫。

emitter.prependOnceListener(eventName, listener)#

將名為 eventName 事件的一次性 listener 函式添加到監聽器陣列的開頭。下一次觸發 eventName 時,此監聽器會被移除,然後被呼叫。

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

傳回對 EventEmitter 的參考,以便可以鏈式呼叫。

emitter.removeAllListeners([eventName])#

移除所有監聽器,或移除指定 eventName 的監聽器。

移除程式碼中其他地方添加的監聽器是不好的做法,尤其是當 EventEmitter 實例是由其他組件或模組(例如 socket 或檔案串流)建立時。

傳回對 EventEmitter 的參考,以便可以鏈式呼叫。

emitter.removeListener(eventName, listener)#

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

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

removeListener() 最多會從監聽器陣列中移除一個監聽器實例。如果單個監聽器已被多次添加到指定 eventName 的監聽器陣列中,則必須多次呼叫 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:
//   A
const 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])#

如果在發送事件時發生 promise rejection 且發送器啟用了 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() 方法暫時避免此警告。

defaultMaxListenersAbortSignal 實例沒有影響。雖然仍可以使用 emitter.setMaxListeners(n) 為單個 AbortSignal 實例設定警告限制,但預設情況下 AbortSignal 實例不會發出警告。

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 發送給定事件時履行 (fulfilled),或者如果 EventEmitter 在等待時發送 'error' 則拒絕 (rejected)。Promise 將解析為一個包含發送到給定事件之所有引數的陣列。

此方法是刻意設計為通用的,並適用於 Web 平台的 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 boom
const { 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(); // 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(); // Prints: Waiting for the event was canceled!

等待多個事件時的注意事項#

使用 events.once() 方法等待多個事件時,注意執行順序非常重要。

傳統事件監聽器在發送事件時會同步呼叫。這保證了在所有監聽器完成執行之前,執行不會超過發送的事件。

在等待由 events.once() 傳回的 Promise 時,情況則不同。Promise 任務直到當前執行堆疊運行完畢後才會處理,這意味著在非同步執行從相關的 await 語句繼續之前,可能會發送多個事件。

因此,如果使用一系列 await events.once() 語句來監聽多個事件,可能會「錯過」事件,因為在事件迴圈的同一階段中可能會發送多個事件。(在使用 process.nextTick() 發送事件時也是如此,因為 process.nextTick() 排隊的任務會在 Promise 任務之前執行。)

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

const myEE = new EventEmitter();

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

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

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

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

const myEE = new EventEmitter();

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

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

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

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

要捕獲多個事件,請在 await 任何一個 Promise 之前先建立所有的 Promise。使用 Promise.all()Promise.race()Promise.allSettled() 通常會讓這變得更容易。

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

const myEE = new EventEmitter();

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

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

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

const myEE = new EventEmitter();

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

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

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

events.captureRejections#

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

events.captureRejectionSymbol#

  • 類型:<symbol> Symbol.for('nodejs.rejection')

請參閱如何編寫自定義的 拒絕處理程式 (rejection handler)

events.listenerCount(emitterOrTarget, eventName)#

傳回名為 eventName 的事件之已註冊監聽器數量。

對於 EventEmitter,此行為與在發送器上呼叫 .listenerCount 完全相同。

對於 EventTarget,這是獲取監聽器數量的唯一方法。這對於除錯和診斷很有用。

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

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

{
  const ee = new EventEmitter();
  ee.on('event', () => {});
  ee.on('event', () => {});
  console.log(listenerCount(ee, 'event')); // 2
}
{
  const et = new EventTarget();
  et.addEventListener('event', () => {});
  et.addEventListener('event', () => {});
  console.log(listenerCount(et, 'event')); // 2
}

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

  • emitter <EventEmitter>
  • eventName <string> | <symbol> 正在被監聽的事件名稱
  • options <Object>
    • signal <AbortSignal> 可用於取消對事件的等待。
    • close <string[]> 將結束迭代的事件名稱。
    • highWaterMark <integer> 預設值: Number.MAX_SAFE_INTEGER。高水位線。每當緩衝的事件大小高於它時,發送器就會暫停。僅在實現了 pause()resume() 方法的發送器上支援。
    • lowWaterMark <integer> 預設值: 1。低水位線。每當緩衝的事件大小低於它時,發送器就會恢復。僅在實現了 pause()resume() 方法的發送器上支援。
  • 傳回:<AsyncIterator>,迭代由 emitter 發送的 eventName 事件。
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 here
const { 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 事件的 AsyncIterator。如果 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)#

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

在中止信號 (abort signals) 上監聽 abort 事件是不安全的,並且可能導致資源洩漏,因為持有該信號的另一個第三方可以呼叫 e.stopImmediatePropagation()。遺憾的是 Node.js 無法更改這一點,因為這會違反 Web 標準。此外,原始 API 容易讓人忘記移除監聽器。

此 API 通過解決這兩個問題,允許在 Node.js API 中安全地使用 AbortSignal,其監聽方式使得 stopImmediatePropagation 不會阻止監聽器運行。

傳回一個可處置對象 (disposable),以便可以更輕鬆地取消訂閱。

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

function example(signal) {
  signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
  // addAbortListener() returns a disposable, so the `using` keyword ensures
  // the abort listener is automatically removed when this scope exits.
  using _ = addAbortListener(signal, (e) => {
    // Do something when signal is aborted.
  });
}
import { addAbortListener } from 'node:events';

function example(signal) {
  signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
  // addAbortListener() returns a disposable, so the `using` keyword ensures
  // the abort listener is automatically removed when this scope exits.
  using _ = addAbortListener(signal, (e) => {
    // Do something when signal is aborted.
  });
}

類別:events.EventEmitterAsyncResource extends EventEmitter#

EventEmitter<AsyncResource> 整合,用於需要手動非同步追蹤的 EventEmitter。具體來說,由 events.EventEmitterAsyncResource 實例發送的所有事件都將在其 非同步上下文 (async context) 內運行。

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 自身相同的方法並採用相同的選項。

new events.EventEmitterAsyncResource([options])#

  • options <Object>
    • captureRejections <boolean> 啟用 自動捕捉 promise rejection預設值: false
    • name <string> 非同步事件的類型。預設值: new.target.name
    • triggerAsyncId <number> 建立此非同步事件的執行上下文 ID。預設值: executionAsyncId()
    • requireManualDestroy <boolean> 如果設定為 true,則在物件被垃圾回收時禁用 emitDestroy。通常不需要設定此項(即使手動呼叫了 emitDestroy),除非檢索了資源的 asyncId 並以此呼叫了敏感 API 的 emitDestroy。當設定為 false 時,只有在至少有一個活動的 destroy 鉤子時,才會在垃圾回收時進行 emitDestroy 呼叫。預設值: false

eventemitterasyncresource.asyncId#

  • 類型:<number> 分配給資源的唯一 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 vs. DOM EventTarget#

Node.js EventTargetEventTarget Web API 之間有兩個主要區別:

  1. 雖然 DOM EventTarget 實例可以是階層式的,但 Node.js 中沒有階層和事件傳播的概念。也就是說,分派到 EventTarget 的事件不會通過嵌套目標物件的階層進行傳播,每個目標物件可能都有自己的一組事件處理程式。
  2. 在 Node.js EventTarget 中,如果事件監聽器是非同步函式或傳回 Promise,且傳回的 Promise 被拒絕,則該拒絕會自動被捕捉,並與同步拋出錯誤的監聽器以相同方式處理(詳見 EventTarget 錯誤處理)。

NodeEventTarget vs. EventEmitter#

NodeEventTarget 物件實現了 EventEmitter API 的修改子集,使其能夠在某些情況下密切地模擬 EventEmitterNodeEventTarget 不是 EventEmitter 的實例,在大多數情況下不能代替 EventEmitter 使用。

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

事件監聽器#

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

在任一情況下,處理程式函式都會被呼叫,並傳遞傳給 eventTarget.dispatchEvent() 函式的 event 引數。

可以使用非同步函式作為事件監聽器。如果非同步處理程式函式被拒絕 (rejects),該拒絕會被捕捉並按照 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 不會像 EventEmitter 那樣為 'error' 類型事件實現任何特殊的預設處理。

目前錯誤在到達 process.on('uncaughtException') 之前會先轉發到 process.on('error') 事件。此行為已被棄用,並將在未來版本中更改,以使 EventTarget 與其他 Node.js API 保持一致。任何依賴 process.on('error') 事件的程式碼都應調整為符合新行為。

類別:Event#

Event 物件是 Event Web API 的改編。實例由 Node.js 內部建立。

event.bubbles#

這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

event.cancelBubble#

穩定性:3 - 舊版 (Legacy):請改用 event.stopPropagation()

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

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

這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

event.composedPath()#

傳回一個陣列,其中包含當前的 EventTarget 作為唯一的條目,或者如果事件未被分派則為空。這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

event.currentTarget#

event.target 的別名。

event.defaultPrevented#

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

event.eventPhase#
  • 類型:<number> 當事件未被分派時傳回 0,正在分派時傳回 2

這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

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

穩定性:3 - 舊版 (Legacy):WHATWG 規範認為它已被棄用,使用者根本不應該使用它。

與事件建構函式多餘且無法設定 composed。這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

event.isTrusted#

<AbortSignal>"abort" 事件在發送時 isTrusted 設定為 true。在所有其他情況下,該值均為 false

event.preventDefault()#

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

event.returnValue#

穩定性:3 - 舊版 (Legacy):請改用 event.defaultPrevented

  • 類型:<boolean> 如果事件未被取消則為 True。

event.returnValue 的值始終與 event.defaultPrevented 相反。這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

event.srcElement#

穩定性:3 - 舊版 (Legacy):請改用 event.target

event.target 的別名。

event.stopImmediatePropagation()#

在當前監聽器完成後停止調用事件監聽器。

event.stopPropagation()#

這在 Node.js 中不使用,提供此屬性純粹是為了完整性。

event.target#
event.timeStamp#

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

event.type#

事件類型識別碼。

類別:EventTarget#

eventTarget.addEventListener(type, listener[, options])#
  • type <string>
  • 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

除了根據 EventTarget 規範追蹤註冊的事件監聽器外,Node.js 不會以任何功能性方式使用 capture 選項。具體來說,capture 選項在註冊 listener 時被用作鍵值的一部分。任何個別的 listener 都可以分別以 capture = falsecapture = 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#

CustomEvent 物件是 CustomEvent Web API 的改編。實例由 Node.js 內部建立。

event.detail#
  • 類型:<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 <string>
  • 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)#

EventTarget 類別的 Node.js 特定擴充,將最大事件監聽器數量設定為 n

nodeEventTarget.getMaxListeners()#

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

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

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

nodeEventTarget.on(type, listener)#

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

nodeEventTarget.once(type, listener)#

EventTarget 類別的 Node.js 特定擴充,為給定的事件 type 添加一個 once 監聽器。這相當於在呼叫 on 時將 once 選項設定為 true

nodeEventTarget.removeAllListeners([type])#

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

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

EventTarget 類別的 Node.js 特定擴充,移除給定 typelistenerremoveListener()removeEventListener() 之間的唯一區別是 removeListener() 將傳回對 EventTarget 的參考。