イベント#

安定性: 2 - Stable

ソースコード: lib/events.js

Node.jsコアAPIの多くは、特定の種類のオブジェクト(「エミッター」と呼ばれる)が名前付きイベントを発行し、それによって`Function`オブジェクト(「リスナー」)が呼び出されるという、慣用的な非同期イベント駆動アーキテクチャを中心に構築されています。

例えば、net.Serverオブジェクトはピアが接続するたびにイベントを発行します。fs.ReadStreamはファイルが開かれたときにイベントを発行します。ストリームはデータが読み込み可能になるたびにイベントを発行します。

イベントを発行するすべてのオブジェクトは、`EventEmitter`クラスのインスタンスです。これらのオブジェクトは`eventEmitter.on()`関数を公開しており、これにより1つ以上の関数をオブジェクトが発行する名前付きイベントにアタッチできます。通常、イベント名はキャメルケースの文字列ですが、任意の有効な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');

非同期 vs. 同期#

`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'`イベントに対して少なくとも1つのリスナーが登録されておらず、`'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のrejectionをキャプチャする#

イベントハンドラで `async` 関数を使用すると、例外がスローされた場合に未処理の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ハンドラがありません。推奨事項は、**`'error'`イベントハンドラとして`async`関数を使用しない**ことです。

クラス: `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()`#

エミッターがリスナーを登録しているイベントをリストした配列を返します。

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)`#

`eventName`という名前のイベントのリスナー配列の末尾に`listener`関数を追加します。`listener`がすでに追加されているかどうかのチェックは行われません。同じ`eventName`と`listener`の組み合わせで複数回呼び出すと、`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)`#

`eventName`という名前のイベントのリスナー配列の*先頭*に`listener`関数を追加します。`listener`がすでに追加されているかどうかのチェックは行われません。同じ`eventName`と`listener`の組み合わせで複数回呼び出すと、`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`インスタンスが他のコンポーネントやモジュール(例:ソケットやファイルストリーム)によって作成された場合には、悪い習慣です。

`EventEmitter`への参照を返すので、呼び出しをチェーンできます。

`emitter.removeListener(eventName, listener)`#

`eventName`という名前のイベントのリスナー配列から、指定された`listener`を削除します。

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

`removeListener()`は、リスナー配列からリスナーのインスタンスを最大で1つ削除します。指定された`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:
//   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)`#

デフォルトでは、`EventEmitter`は特定のイベントに対して`10`個以上のリスナーが追加されると警告を出力します。これはメモリリークを見つけるのに役立つ便利なデフォルトです。`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])`#

`Symbol.for('nodejs.rejection')` メソッドは、イベントを発行する際にPromiseのrejectionが発生し、かつエミッターで `captureRejections` が有効になっている場合に呼び出されます。`Symbol.for('nodejs.rejection')` の代わりに `events.captureRejectionSymbol` を使用することも可能です。

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`個のリスナーを登録できます。この制限は、個々の`EventEmitter`インスタンスに対して`emitter.setMaxListeners(n)`メソッドを使用して変更できます。*すべての*`EventEmitter`インスタンスのデフォルトを変更するには、`events.defaultMaxListeners`プロパティを使用できます。この値が正の数でない場合、`RangeError`がスローされます。

`events.defaultMaxListeners`を設定する際には注意してください。この変更は、変更が行われる前に作成されたものを含め、*すべて*の`EventEmitter`インスタンスに影響します。ただし、`emitter.setMaxListeners(n)`の呼び出しは、`events.defaultMaxListeners`よりも優先されます。

これはハードリミットではありません。`EventEmitter`インスタンスはより多くのリスナーの追加を許可しますが、「EventEmitterのメモリリークの可能性」が検出されたことを示すトレース警告をstderrに出力します。どの単一の`EventEmitter`に対しても、`emitter.getMaxListeners()`と`emitter.setMaxListeners()`メソッドを使用してこの警告を一時的に回避できます。

`defaultMaxListeners` は `AbortSignal` インスタンスには影響しません。`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')`で検査でき、イベントエミッターインスタンス、イベント名、アタッチされたリスナーの数をそれぞれ参照する追加の`emitter`、`type`、および`count`プロパティを持ちます。その`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])`#

`EventEmitter`が指定されたイベントを発行したときにfulfillされるか、待機中に`EventEmitter`が`'error'`を発行した場合にrejectされる`Promise`を作成します。`Promise`は、指定されたイベントに発行されたすべての引数の配列でresolveされます。

このメソッドは意図的に汎用的であり、特別な`'error'`イベントのセマンティクスを持たず、`'error'`イベントをリッスンしないWebプラットフォームのEventTargetインターフェースと連携します。

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();

`'error'`イベントの特別な扱いは、`events.once()`が他のイベントを待つために使用される場合にのみ適用されます。`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(); // 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!

`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> `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])`#

  • `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 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`イベントをイテレートする`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` イベントを一度だけリッスンします。

AbortSignalの`abort`イベントをリッスンすることは安全ではなく、リソースリークにつながる可能性があります。なぜなら、そのシグナルを持つ別の第三者が`e.stopImmediatePropagation()`を呼び出すことができるからです。残念ながら、Node.jsはWeb標準に違反するため、これを変更できません。さらに、元のAPIではリスナーの削除を忘れやすくなっています。

このAPIは、`stopImmediatePropagation`がリスナーの実行を妨げないようにイベントをリッスンすることで、これら2つの問題を解決し、Node.js APIで`AbortSignal`を安全に使用できるようにします。

より簡単に購読解除できるように、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`のために、`EventEmitter`を<AsyncResource>と統合します。具体的には、`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`クラスは、`EventEmitter`および`AsyncResource`自体と同じメソッドを持ち、同じオプションを取ります。

`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`に設定すると、ガベージコレクション時の`emitDestroy`呼び出しは、アクティブな`destroy`フックが少なくとも1つ存在する場合にのみ行われます。デフォルト: `false`。

`eventemitterasyncresource.asyncId`#

  • 型: <number> リソースに割り当てられた一意の`asyncId`。

`eventemitterasyncresource.asyncResource`#

返された`AsyncResource`オブジェクトには、この`EventEmitterAsyncResource`への参照を提供する追加の`eventEmitter`プロパティがあります。

`eventemitterasyncresource.emitDestroy()`#

すべての`destroy`フックを呼び出します。これは一度だけ呼び出すべきです。複数回呼び出すとエラーがスローされます。これは手動で呼び出す**必要があります**。リソースがGCによって収集されるに任せると、`destroy`フックは決して呼び出されません。

`eventemitterasyncresource.triggerAsyncId`#

  • 型: <number> `AsyncResource`コンストラクタに渡されるのと同じ`triggerAsyncId`。

`EventTarget` および `Event` API#

`EventTarget`および`Event`オブジェクトは、Node.jsコアAPIの一部で公開されている`EventTarget` Web APIのNode.js固有の実装です。

const target = new EventTarget();

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

Node.js `EventTarget` vs. DOM `EventTarget`#

Node.js `EventTarget`と`EventTarget` Web APIには2つの重要な違いがあります。

  1. DOMの`EventTarget`インスタンスは階層的である*場合があり*ますが、Node.jsには階層やイベント伝播の概念はありません。つまり、`EventTarget`にディスパッチされたイベントは、それぞれがイベントに対する独自のハンドラセットを持つ可能性のあるネストされたターゲットオブジェクトの階層を伝播しません。
  2. Node.jsの`EventTarget`では、イベントリスナーが非同期関数であるか、`Promise`を返す場合、返された`Promise`がrejectされると、そのrejectionは自動的にキャプチャされ、同期的にスローするリスナーと同じように処理されます(詳細は`EventTarget`のエラーハンドリングを参照)。

`NodeEventTarget` vs. `EventEmitter`#

`NodeEventTarget`オブジェクトは、特定の状況で`EventEmitter`を密接に*エミュレート*することを可能にする、変更された`EventEmitter` APIのサブセットを実装しています。`NodeEventTarget`は`EventEmitter`のインスタンスでは*なく*、ほとんどの場合、`EventEmitter`の代わりに使用することはできません。

  1. `EventEmitter`とは異なり、特定の`listener`はイベント`type`ごとに最大1回しか登録できません。`listener`を複数回登録しようとする試みは無視されます。
  2. `NodeEventTarget`は完全な`EventEmitter` APIをエミュレートしていません。具体的には、`prependListener()`、`prependOnceListener()`、`rawListeners()`、および`errorMonitor` APIはエミュレートされません。`'newListener'`および`'removeListener'`イベントも発行されません。
  3. `NodeEventTarget`は、タイプが`'error'`のイベントに対する特別なデフォルトの振る舞いを実装していません。
  4. `NodeEventTarget`は、すべてのイベントタイプに対して、`EventListener`オブジェクトおよび関数をハンドラとしてサポートします。

イベントリスナー#

イベント`type`に登録されたイベントリスナーは、JavaScript関数か、値が関数である`handleEvent`プロパティを持つオブジェクトのいずれかです。

どちらの場合でも、ハンドラ関数は`eventTarget.dispatchEvent()`関数に渡された`event`引数で呼び出されます。

非同期関数をイベントリスナーとして使用できます。非同期ハンドラ関数がrejectした場合、そのrejectionはキャプチャされ、`EventTarget`のエラーハンドリングで説明されているように処理されます。

1つのハンドラ関数によってスローされたエラーは、他のハンドラの呼び出しを妨げません。

ハンドラ関数の戻り値は無視されます。

ハンドラは常に追加された順に呼び出されます。

ハンドラ関数は`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` のエラーハンドリング#

登録されたイベントリスナーがスロー(またはrejectする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`#
  • 型: <boolean> 常に `false` を返します。

これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.cancelBubble`#

安定性: 3 - レガシー: 代わりに `event.stopPropagation()` を使用してください。

`true`に設定された場合、`event.stopPropagation()`のエイリアスです。これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.cancelable`#
  • 型: <boolean> イベントが `cancelable` オプションで作成された場合は true。
`event.composed`#
  • 型: <boolean> 常に `false` を返します。

これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.composedPath()`#

現在の`EventTarget`を唯一のエントリとして含む配列を返すか、イベントがディスパッチされていない場合は空の配列を返します。これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.currentTarget`#
  • 型: <EventTarget> イベントをディスパッチしている `EventTarget`。

`event.target` のエイリアスです。

`event.defaultPrevented`#

`cancelable`が`true`で、`event.preventDefault()`が呼び出された場合に`true`になります。

`event.eventPhase`#
  • 型: <number> イベントがディスパッチされていない間は `0` を、ディスパッチ中は `2` を返します。

これはNode.jsでは使用されず、純粋に完全性のために提供されています。

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

安定性: 3 - レガシー: WHATWG仕様では非推奨とされており、ユーザーは一切使用すべきではありません。

イベントコンストラクタと冗長であり、`composed`を設定することができません。これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.isTrusted`#

<AbortSignal> の `"abort"` イベントは `isTrusted` が `true` に設定されて発行されます。他のすべてのケースでは値は `false` です。

`event.preventDefault()`#

`cancelable`が`true`の場合、`defaultPrevented`プロパティを`true`に設定します。

`event.returnValue`#

安定性: 3 - レガシー: 代わりに `event.defaultPrevented` を使用してください。

  • 型: <boolean> イベントがキャンセルされていない場合は true。

`event.returnValue`の値は常に`event.defaultPrevented`の反対です。これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.srcElement`#

安定性: 3 - レガシー: 代わりに `event.target` を使用してください。

  • 型: <EventTarget> イベントをディスパッチしている `EventTarget`。

`event.target` のエイリアスです。

`event.stopImmediatePropagation()`#

現在のイベントリスナーが完了した後、イベントリスナーの呼び出しを停止します。

`event.stopPropagation()`#

これはNode.jsでは使用されず、純粋に完全性のために提供されています。

`event.target`#
  • 型: <EventTarget> イベントをディスパッチしている `EventTarget`。
`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`の場合、`listener`は次に`type`イベントがディスパッチされた後に削除されます。

`capture`オプションは、`EventTarget`仕様に従って登録されたイベントリスナーを追跡する以外に、Node.jsで機能的に使用されることはありません。具体的には、`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.type`のハンドラリストに`event`をディスパッチします。

登録されたイベントリスナーは、登録された順序で同期的に呼び出されます。

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

イベント`type`のハンドラリストから`listener`を削除します。

クラス: `CustomEvent`#

`CustomEvent`オブジェクトは`CustomEvent` Web APIを改作したものです。インスタンスはNode.js内部で作成されます。

`event.detail`#
  • 型: <any> 初期化時に渡されたカスタムデータを返します。

読み取り専用です。

クラス: `NodeEventTarget`#

`NodeEventTarget`は、`EventEmitter` APIのサブセットをエミュレートする、`EventTarget`のNode.js固有の拡張です。

`nodeEventTarget.addListener(type, listener)`#

同等の`EventEmitter` APIをエミュレートする`EventTarget`クラスのNode.js固有の拡張です。`addListener()`と`addEventListener()`の唯一の違いは、`addListener()`が`EventTarget`への参照を返すことです。

`nodeEventTarget.emit(type, arg)`#
  • `type` <string>
  • `arg` <any>
  • 戻り値: <boolean> `type` に登録されたイベントリスナーが存在する場合は `true`、それ以外の場合は `false`。

`type`のハンドラリストに`arg`をディスパッチする`EventTarget`クラスのNode.js固有の拡張です。

`nodeEventTarget.eventNames()`#

イベントリスナーが登録されているイベント`type`名の配列を返す、`EventTarget`クラスのNode.js固有の拡張です。

`nodeEventTarget.listenerCount(type)`#

`type`に登録されているイベントリスナーの数を返す、`EventTarget`クラスのNode.js固有の拡張です。

`nodeEventTarget.setMaxListeners(n)`#

最大イベントリスナー数を`n`として設定する、`EventTarget`クラスのNode.js固有の拡張です。

`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)`#

指定されたイベント`type`に対して`once`リスナーを追加する`EventTarget`クラスのNode.js固有の拡張です。これは、`once`オプションを`true`に設定して`on`を呼び出すことと同等です。

`nodeEventTarget.removeAllListeners([type])`#

`EventTarget`クラスのNode.js固有の拡張です。`type`が指定されている場合、`type`に登録されているすべてのリスナーを削除します。そうでない場合は、登録されているすべてのリスナーを削除します。

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

指定された`type`の`listener`を削除する`EventTarget`クラスのNode.js固有の拡張です。`removeListener()`と`removeEventListener()`の唯一の違いは、`removeListener()`が`EventTarget`への参照を返すことです。