イベント
ソースコード: lib/events.js
Node.js コア API の多くは、特定の種類のオブジェクト(「エミッター」と呼ばれる)が名前付きイベントを発行し、それによって Function
オブジェクト(「リスナー」)が呼び出されるという、慣用的な非同期イベント駆動アーキテクチャに基づいて構築されています。
例えば、net.Server
オブジェクトは、ピアが接続するたびにイベントを発行します。fs.ReadStream
は、ファイルが開かれたときにイベントを発行します。 stream は、読み取り可能なデータがあるたびにイベントを発行します。
イベントを発行するすべてのオブジェクトは、EventEmitter
クラスのインスタンスです。 これらのオブジェクトは、オブジェクトによって発行された名前付きイベントに 1 つ以上の関数をアタッチできる 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');
非同期 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: 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'
イベントに対して少なくとも1つのリスナーを登録 していない 場合、'error'
イベントが発火されると、エラーがスローされ、スタックトレースが出力され、Node.jsプロセスが終了します。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// スローされ、Node.jsがクラッシュします
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// スローされ、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!'));
// それでもスローされ、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!'));
// それでもスローされ、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'
イベントには、無限のエラーループを回避するためのキャッチハンドラーがありません。async
関数を'error'
イベントハンドラーとして使用しないことをお勧めします。
クラス: EventEmitter
[履歴]
バージョン | 変更 |
---|---|
v13.4.0, v12.16.0 | captureRejections オプションが追加されました。 |
v0.1.26 | 追加: v0.1.26 |
EventEmitter
クラスは node:events
モジュールによって定義され、公開されています。
import { EventEmitter } from 'node:events';
const EventEmitter = require('node:events');
すべての EventEmitter
は、新しいリスナーが追加されると 'newListener'
イベントを発行し、既存のリスナーが削除されると 'removeListener'
イベントを発行します。
以下のオプションをサポートしています。
captureRejections
<boolean> Promise のリジェクトの自動キャプチャを有効にします。 デフォルト:false
。
イベント: 'newListener'
追加: v0.1.26
eventName
<string> | <symbol> リッスンされるイベントの名前listener
<Function> イベントハンドラ関数
EventEmitter
インスタンスは、リスナーがリスナーの内部配列に追加される前に、独自の 'newListener'
イベントを発行します。
'newListener'
イベントに登録されたリスナーには、イベント名と、追加されるリスナーへの参照が渡されます。
イベントがリスナーの追加前にトリガーされるという事実は、微妙ですが重要な副作用があります。 'newListener'
コールバック内で同じ name
に登録された追加のリスナーは、追加処理中のリスナーの前に挿入されます。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// ループしないように一度だけ実行します
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// 前に新しいリスナーを挿入します
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Prints:
// B
// A
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// ループしないように一度だけ実行します
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// 前に新しいリスナーを挿入します
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Prints:
// B
// A
イベント: 'removeListener'
[履歴]
バージョン | 変更点 |
---|---|
v6.1.0, v4.7.0 | .once() を使ってアタッチされたリスナーに対して、listener 引数は元のリスナー関数を生成するようになりました。 |
v0.9.3 | 追加: v0.9.3 |
eventName
<string> | <symbol> イベント名listener
<Function> イベントハンドラ関数
'removeListener'
イベントは、listener
が削除された 後 に発生します。
emitter.addListener(eventName, listener)
追加: v0.1.26
eventName
<string> | <symbol>listener
<Function>
emitter.on(eventName, listener)
のエイリアスです。
emitter.emit(eventName[, ...args])
追加: v0.1.26
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()
Added in: v6.0.0
- 戻り値: <Array>
emitter がリスナーを登録しているイベントをリストした配列を返します。配列の値は、文字列または 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()
Added in: v1.0.0
- 戻り値: <integer>
EventEmitter
の現在の最大リスナー値を返します。これは、emitter.setMaxListeners(n)
によって設定されるか、デフォルトで events.defaultMaxListeners
になります。
emitter.listenerCount(eventName[, listener])
[History]
Version | Changes |
---|---|
v19.8.0, v18.16.0 | listener 引数が追加されました。 |
v3.2.0 | Added in: v3.2.0 |
eventName
<string> | <symbol> リッスンしているイベントの名前listener
<Function> イベントハンドラー関数- 戻り値: <integer>
eventName
という名前のイベントをリッスンしているリスナーの数を返します。listener
が提供されている場合は、イベントのリスナーのリストでリスナーが見つかった回数を返します。
emitter.listeners(eventName)
[履歴]
バージョン | 変更 |
---|---|
v7.0.0 | .once() を使用してアタッチされたリスナーの場合、ラッパー関数の代わりに元のリスナーが返されるようになりました。 |
v0.1.26 | Added in: v0.1.26 |
eventName
<string> | <symbol>- 戻り値: <Function[]>
eventName
という名前のイベントのリスナーの配列のコピーを返します。
server.on('connection', (stream) => {
console.log('誰かが接続しました!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
emitter.off(eventName, listener)
Added in: v10.0.0
eventName
<string> | <symbol>listener
<Function>- 戻り値: <EventEmitter>
emitter.removeListener()
のエイリアスです。
emitter.on(eventName, listener)
Added in: v0.1.101
eventName
<string> | <symbol> イベントの名前。listener
<Function> コールバック関数- 戻り値: <EventEmitter>
listener
関数を、eventName
という名前のイベントのリスナー配列の末尾に追加します。 listener
が既に追加されているかどうかを確認するためのチェックは行われません。 同じ eventName
と listener
の組み合わせを渡す複数の呼び出しは、listener
が複数回追加され、呼び出される結果になります。
server.on('connection', (stream) => {
console.log('誰かが接続しました!');
});
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)
Added in: v0.3.0
eventName
<string> | <symbol> イベントの名前。listener
<Function> コールバック関数- 戻り値: <EventEmitter>
eventName
という名前のイベントに対して1回限りのlistener
関数を追加します。次にeventName
がトリガーされると、このリスナーは削除され、その後呼び出されます。
server.once('connection', (stream) => {
console.log('ああ、初めてのユーザーだ!');
});
呼び出しをチェーンできるように、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)
Added in: v6.0.0
eventName
<string> | <symbol> イベントの名前。listener
<Function> コールバック関数- 戻り値: <EventEmitter>
listener
関数を、eventName
という名前のイベントのリスナー配列の先頭に追加します。listener
が既に追加されているかどうかを確認するためのチェックは行われません。同じeventName
とlistener
の組み合わせを渡して複数回呼び出すと、listener
が複数回追加され、呼び出されます。
server.prependListener('connection', (stream) => {
console.log('誰かが接続しました!');
});
呼び出しをチェーンできるように、EventEmitter
への参照を返します。
emitter.prependOnceListener(eventName, listener)
Added in: v6.0.0
eventName
<string> | <symbol> イベントの名前。listener
<Function> コールバック関数- 戻り値: <EventEmitter>
eventName
という名前のイベントに対する 1 回限り の listener
関数を、リスナー配列の 先頭 に追加します。 次回 eventName
がトリガーされると、このリスナーは削除され、その後呼び出されます。
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
EventEmitter
への参照を返すので、呼び出しをチェーンできます。
emitter.removeAllListeners([eventName])
Added in: v0.1.26
eventName
<string> | <symbol>- 戻り値: <EventEmitter>
すべてのリスナー、または指定された eventName
のリスナーを削除します。
コードの別の場所で追加されたリスナーを削除すること、特に EventEmitter
インスタンスが他のコンポーネントまたはモジュール (ソケットやファイルストリームなど) によって作成された場合は、望ましくありません。
EventEmitter
への参照を返すので、呼び出しをチェーンできます。
emitter.removeListener(eventName, listener)
Added in: v0.1.26
eventName
<string> | <symbol>listener
<Function>- 戻り値: <EventEmitter>
指定された listener
を、eventName
という名前のイベントのリスナー配列から削除します。
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:
// 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)
追加: v0.3.5
n
<integer>- 戻り値: <EventEmitter>
デフォルトでは、特定のイベントに対して 10
個を超えるリスナーが追加されると、EventEmitter
は警告を出力します。これは、メモリリークを見つけるのに役立つ便利なデフォルトです。emitter.setMaxListeners()
メソッドを使用すると、この特定の EventEmitter
インスタンスの制限を変更できます。値は、無制限のリスナーを示すために Infinity
(または 0
) に設定できます。
EventEmitter
への参照を返すため、呼び出しをチェーンできます。
emitter.rawListeners(eventName)
追加: v9.4.0
eventName
<string> | <symbol>- 戻り値: <Function[]>
.once()
で作成されたラッパーなど、eventName
という名前のイベントのリスナーの配列のコピーを返します。
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// `onceWrapper` という関数を持つ新しい配列を返します。この関数には、上記でバインドされた元のリスナーを含むプロパティ `listener` があります。
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// コンソールに "log once" と出力し、`once` イベントのバインドを解除しません
logFnWrapper.listener();
// コンソールに "log once" と出力し、リスナーを削除します
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// 上記の `.on()` によってバインドされた単一の関数を持つ新しい配列を返します
const newListeners = emitter.rawListeners('log');
// "log persistently" を 2 回出力します
newListeners[0]();
emitter.emit('log');
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// `onceWrapper` という関数を持つ新しい配列を返します。この関数には、上記でバインドされた元のリスナーを含むプロパティ `listener` があります。
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// コンソールに "log once" と出力し、`once` イベントのバインドを解除しません
logFnWrapper.listener();
// コンソールに "log once" と出力し、リスナーを削除します
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// 上記の `.on()` によってバインドされた単一の関数を持つ新しい配列を返します
const newListeners = emitter.rawListeners('log');
// "log persistently" を 2 回出力します
newListeners[0]();
emitter.emit('log');
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
[履歴]
バージョン | 変更点 |
---|---|
v17.4.0, v16.14.0 | 実験的ではなくなりました。 |
v13.4.0, v12.16.0 | 追加: v13.4.0, v12.16.0 |
Symbol.for('nodejs.rejection')
メソッドは、イベントの発行時に Promise のリジェクトが発生し、captureRejections
が EventEmitter で有効になっている場合に呼び出されます。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
追加: v0.11.2
デフォルトでは、単一のイベントに対して最大 10
個のリスナーを登録できます。 この制限は、emitter.setMaxListeners(n)
メソッドを使用して、個々の EventEmitter
インスタンスに対して変更できます。 すべての 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
追加: v13.6.0, v12.17.0
このシンボルは、'error'
イベントのみを監視するためのリスナーをインストールするために使用されます。このシンボルを使用してインストールされたリスナーは、通常の 'error'
リスナーが呼び出される前に呼び出されます。
このシンボルを使用してリスナーをインストールしても、'error'
イベントが発行された後の動作は変更されません。したがって、通常の 'error'
リスナーがインストールされていない場合、プロセスは引き続きクラッシュします。
events.getEventListeners(emitterOrTarget, eventName)
追加: v15.2.0, v14.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>eventName
<string> | <symbol>- 戻り値: <Function[]>
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)
Added in: v19.9.0, v18.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>- 戻り値: <number>
現在設定されているリスナーの最大数を返します。
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])
[履歴]
バージョン | 変更 |
---|---|
v15.0.0 | signal オプションがサポートされるようになりました。 |
v11.13.0, v10.16.0 | Added in: v11.13.0, v10.16.0 |
emitter
<EventEmitter>options
<Object>signal
<AbortSignal> イベントの待機をキャンセルするために使用できます。
戻り値: <Promise>
EventEmitter
が指定されたイベントを発行したときに履行される Promise
を作成します。または、待機中に EventEmitter
が 'error'
を発行した場合は拒否されます。Promise
は、指定されたイベントに発行されたすべての引数の配列で解決されます。
このメソッドは意図的に汎用的であり、特別な '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 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!
process.nextTick()
で発生する複数のイベントの待機
process.nextTick()
操作の同じバッチ内で、または複数のイベントが同期的に発生する場合に、events.once()
関数を使用して複数のイベントを待機するときに注意すべきエッジケースがあります。具体的には、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');
// この Promise は、'foo' イベントが Promise が作成される前に
// 既に発生しているため、決して解決されません。
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');
// この Promise は、'foo' イベントが Promise が作成される前に
// 既に発生しているため、決して解決されません。
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
[履歴]
バージョン | 変更 |
---|---|
v17.4.0, v16.14.0 | 実験的ではなくなりました。 |
v13.4.0, v12.16.0 | 追加: v13.4.0, v12.16.0 |
値: <boolean>
すべての新しい EventEmitter
オブジェクトのデフォルトの captureRejections
オプションを変更します。
events.captureRejectionSymbol
[履歴]
バージョン | 変更 |
---|---|
v17.4.0, v16.14.0 | 実験的ではなくなりました。 |
v13.4.0, v12.16.0 | 追加: v13.4.0, v12.16.0 |
値: Symbol.for('nodejs.rejection')
カスタムのリジェクションハンドラーの書き方をご覧ください。
events.listenerCount(emitter, eventName)
追加: v0.9.12
非推奨: v3.2.0
[安定版: 0 - 非推奨]
安定版: 0 安定性: 0 - 非推奨: 代わりに emitter.listenerCount()
を使用してください。
emitter
<EventEmitter> クエリーするエミッターeventName
<string> | <symbol> イベント名
与えられた emitter
に登録されている、与えられた eventName
のリスナーの数を返すクラスメソッドです。
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
const { 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])
[履歴]
バージョン | 変更 |
---|---|
v22.0.0, v20.13.0 | 一貫性のため、highWaterMark および lowWaterMark オプションをサポートします。 古いオプションも引き続きサポートされています。 |
v20.0.0 | close 、highWatermark 、および lowWatermark オプションがサポートされるようになりました。 |
v13.6.0, v12.16.0 | Added in: v13.6.0, v12.16.0 |
emitter
<EventEmitter>options
<Object>signal
<AbortSignal> イベントの待機をキャンセルするために使用できます。close
- <string[]> イテレーションを終了するイベントの名前。highWaterMark
- <integer> デフォルト:Number.MAX_SAFE_INTEGER
高水位標。 バッファリングされるイベントのサイズがこれよりも大きい場合、エミッターは毎回一時停止されます。pause()
メソッドとresume()
メソッドを実装するエミッターでのみサポートされます。lowWaterMark
- <integer> デフォルト:1
低水位標。 バッファリングされるイベントのサイズがこれよりも小さい場合、エミッターは毎回再開されます。pause()
メソッドとresume()
メソッドを実装するエミッターでのみサポートされます。
戻り値:
emitter
によって発行されたeventName
イベントをイテレートする <AsyncIterator>
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// 後で発行
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// この内部ブロックの実行は同期的であり、
// 一度に 1 つのイベントを処理します (await を使用しても)。 使用しないでください
// 同時実行が必要な場合。
console.log(event); // prints ['bar'] [42]
}
// ここには到達できません
const { on, EventEmitter } = require('node:events');
(async () => {
const ee = new EventEmitter();
// 後で発行
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// この内部ブロックの実行は同期的であり、
// 一度に 1 つのイベントを処理します (await を使用しても)。 使用しないでください
// 同時実行が必要な場合。
console.log(event); // prints ['bar'] [42]
}
// ここには到達できません
})();
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();
// 後で発行
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// この内部ブロックの実行は同期的であり、
// 一度に 1 つのイベントを処理します (await を使用しても)。 使用しないでください
// 同時実行が必要な場合。
console.log(event); // prints ['bar'] [42]
}
// ここには到達できません
})();
process.nextTick(() => ac.abort());
const { on, EventEmitter } = require('node:events');
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// 後で発行
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// この内部ブロックの実行は同期的であり、
// 一度に 1 つのイベントを処理します (await を使用しても)。 使用しないでください
// 同時実行が必要な場合。
console.log(event); // prints ['bar'] [42]
}
// ここには到達できません
})();
process.nextTick(() => ac.abort());
events.setMaxListeners(n[, ...eventTargets])
追加: v15.4.0
n
<number> 負でない数値。EventTarget
イベントごとのリスナーの最大数。...eventsTargets
<EventTarget[]> | <EventEmitter[]> ゼロ個以上の<EventTarget>または<EventEmitter>のインスタンス。何も指定しない場合、n
は新しく作成されるすべての<EventTarget>および<EventEmitter>オブジェクトのデフォルトの最大値として設定されます。
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)
追加: v20.5.0, v18.18.0
signal
<AbortSignal>listener
<Function> | <EventListener>- 戻り値: <Disposable>
abort
リスナーを削除するDisposable。
指定された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
追加: v17.4.0, v16.14.0
手動の非同期追跡を必要とする 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';
// 非同期追跡ツールはこれを 'Q' として識別します。
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// 'foo' リスナーは EventEmitters の非同期コンテキストで実行されます。
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// ただし、非同期コンテキストを追跡しない通常の EventEmitters の 'foo' リスナーは、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 } from 'node:async_hooks';
// 非同期追跡ツールはこれを 'Q' として識別します。
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// 'foo' リスナーは EventEmitters の非同期コンテキストで実行されます。
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// ただし、非同期コンテキストを追跡しない通常の EventEmitters の 'foo' リスナーは、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のリジェクトの自動キャプチャを有効にします。デフォルト:false
。name
<string> 非同期イベントのタイプ。デフォルト:new.target.name
。triggerAsyncId
<number> この非同期イベントを作成した実行コンテキストのID。デフォルト:executionAsyncId()
。requireManualDestroy
<boolean>true
に設定すると、オブジェクトがガベージコレクションされるときにemitDestroy
が無効になります。リソースのasyncId
が取得され、機密性の高いAPIのemitDestroy
がそれとともに呼び出される場合を除き、通常、これを設定する必要はありません(emitDestroy
が手動で呼び出された場合でも)。false
に設定すると、ガベージコレクションでのemitDestroy
呼び出しは、少なくとも1つのアクティブなdestroy
フックがある場合にのみ実行されます。デフォルト:false
。
eventemitterasyncresource.asyncId
- Type: <number> リソースに割り当てられた一意の
asyncId
。
eventemitterasyncresource.asyncResource
- Type: 基になる<AsyncResource>。
返された AsyncResource
オブジェクトには、この EventEmitterAsyncResource
への参照を提供する追加の eventEmitter
プロパティがあります。
eventemitterasyncresource.emitDestroy()
すべての destroy
フックを呼び出します。これは一度だけ呼び出す必要があります。複数回呼び出すとエラーがスローされます。これは手動で呼び出す必要があります。リソースがGCによって収集されるまで放置されると、destroy
フックは決して呼び出されません。
eventemitterasyncresource.triggerAsyncId
- タイプ: <number>
AsyncResource
コンストラクターに渡されるのと同じtriggerAsyncId
。
EventTarget
と Event
API
[履歴]
バージョン | 変更 |
---|---|
v16.0.0 | EventTarget のエラー処理を変更しました。 |
v15.4.0 | 実験的ではなくなりました。 |
v15.0.0 | EventTarget および Event クラスがグローバル変数として利用できるようになりました。 |
v14.5.0 | 追加: v14.5.0 |
EventTarget
および Event
オブジェクトは、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 EventTarget
と EventTarget
Web API には、2 つの重要な違いがあります。
NodeEventTarget
と EventEmitter
の比較
NodeEventTarget
オブジェクトは、特定の状況で EventEmitter
を厳密にエミュレートできるようにする、EventEmitter
API の変更されたサブセットを実装します。 NodeEventTarget
は EventEmitter
のインスタンスではありません。ほとんどの場合、EventEmitter
の代わりに使用することはできません。
イベントリスナー
イベント type
に登録されたイベントリスナーは、JavaScript 関数、または値が関数の handleEvent
プロパティを持つオブジェクトのいずれかになります。
どちらの場合も、ハンドラー関数は eventTarget.dispatchEvent()
関数に渡される event
引数を使用して呼び出されます。
非同期関数をイベントリスナーとして使用できます。 非同期ハンドラー関数が拒否された場合、拒否はキャプチャされ、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
エラー処理
登録されたイベントリスナーが例外をスローする(またはリジェクトされる Promise を返す)場合、デフォルトでは、エラーは process.nextTick()
上でキャッチされない例外として扱われます。これは、EventTarget
でキャッチされない例外が発生すると、デフォルトで Node.js プロセスが終了することを意味します。
イベントリスナー内で例外をスローしても、他の登録されたハンドラーの呼び出しが停止されることは ありません。
EventTarget
は、EventEmitter
のように、'error'
タイプのイベントに対する特別なデフォルト処理を実装していません。
現在、エラーは最初に process.on('error')
イベントに転送されてから、process.on('uncaughtException')
に到達します。この動作は非推奨であり、将来のリリースで EventTarget
を他の Node.js API と整合するように変更されます。process.on('error')
イベントに依存するすべてのコードは、新しい動作に合わせて調整する必要があります。
Class: Event
[履歴]
バージョン | 変更 |
---|---|
v15.0.0 | Event クラスがグローバルオブジェクトを通じて利用可能になりました。 |
v14.5.0 | 追加: v14.5.0 |
Event
オブジェクトは、Event
Web API の適応です。インスタンスは Node.js によって内部的に作成されます。
event.bubbles
追加: v14.5.0
- 型: <boolean> 常に
false
を返します。
これは Node.js では使用されず、完全性のためだけに提供されています。
event.cancelBubble
追加: v14.5.0
[安定版: 3 - レガシー]
安定版: 3 安定度: 3 - レガシー: 代わりに event.stopPropagation()
を使用してください。
- 型: <boolean>
true
に設定されている場合、event.stopPropagation()
のエイリアスです。これは Node.js では使用されず、完全性のためだけに提供されています。
event.cancelable
追加: v14.5.0
- 型: <boolean> イベントが
cancelable
オプションを使用して作成された場合は true。
event.composed
Added in: v14.5.0
- Type: <boolean> 常に
false
を返します。
これはNode.jsでは使用されず、完全を期すためにのみ提供されています。
event.composedPath()
Added in: v14.5.0
現在の EventTarget
を唯一のエントリーとして含む配列を返します。イベントがディスパッチされていない場合は空です。これはNode.jsでは使用されず、完全を期すためにのみ提供されています。
event.currentTarget
Added in: v14.5.0
- Type: <EventTarget> イベントをディスパッチしている
EventTarget
。
event.target
のエイリアス。
event.defaultPrevented
Added in: v14.5.0
- Type: <boolean>
cancelable
が true
であり、event.preventDefault()
が呼び出された場合は true
。
event.eventPhase
Added in: v14.5.0
- Type: <number> イベントがディスパッチされていない間は
0
を返し、ディスパッチされている間は2
を返します。
これはNode.jsでは使用されず、完全を期すためにのみ提供されています。
event.initEvent(type[, bubbles[, cancelable]])
Added in: v19.5.0
[Stable: 3 - Legacy]
Stable: 3 Stability: 3 - レガシー: WHATWG仕様では非推奨とされており、ユーザーはまったく使用すべきではありません。
イベントコンストラクターと冗長であり、composed
を設定できません。これはNode.jsでは使用されず、完全を期すためにのみ提供されています。
event.isTrusted
Added in: v14.5.0
- Type: <boolean>
<AbortSignal> "abort"
イベントは、isTrusted
が true
に設定されて発行されます。それ以外の場合は false
です。
event.preventDefault()
Added in: v14.5.0
cancelable
が true
の場合、defaultPrevented
プロパティを true
に設定します。
event.returnValue
Added in: v14.5.0
[Stable: 3 - Legacy]
Stable: 3 Stability: 3 - Legacy: 代わりに event.defaultPrevented
を使用してください。
- Type: <boolean> イベントがキャンセルされていない場合は true。
event.returnValue
の値は常に event.defaultPrevented
の反対です。 これは Node.js では使用されず、完全に網羅するために提供されています。
event.srcElement
Added in: v14.5.0
[Stable: 3 - Legacy]
Stable: 3 Stability: 3 - Legacy: 代わりに event.target
を使用してください。
- Type: <EventTarget> イベントをディスパッチする
EventTarget
。
event.target
のエイリアス。
event.stopImmediatePropagation()
Added in: v14.5.0
現在のイベントリスナーが完了した後、イベントリスナーの呼び出しを停止します。
event.stopPropagation()
Added in: v14.5.0
これは Node.js では使用されず、完全に網羅するために提供されています。
event.target
Added in: v14.5.0
- Type: <EventTarget> イベントをディスパッチする
EventTarget
。
event.timeStamp
Added in: v14.5.0
- Type: <number>
Event
オブジェクトが作成されたときのミリ秒単位のタイムスタンプ。
event.type
Added in: v14.5.0
- Type: <string>
イベントタイプ識別子。
Class: EventTarget
[History]
Version | Changes |
---|---|
v15.0.0 | EventTarget クラスがグローバルオブジェクトから利用可能になりました。 |
v14.5.0 | Added in: v14.5.0 |
eventTarget.addEventListener(type, listener[, options])
[History]
Version | Changes |
---|---|
v15.4.0 | signal オプションのサポートを追加。 |
v14.5.0 | Added in: v14.5.0 |
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)
Added in: v14.5.0
event
<Event>- 戻り値: <boolean> event の
cancelable
属性値が false であるか、またはpreventDefault()
メソッドが呼び出されなかった場合はtrue
。それ以外の場合はfalse
。
event.type
のハンドラーのリストに event
をディスパッチします。
登録されたイベントリスナーは、登録された順に同期的に呼び出されます。
eventTarget.removeEventListener(type, listener[, options])
Added in: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
イベント type
のハンドラーのリストから listener
を削除します。
Class: CustomEvent
[History]
Version | Changes |
---|---|
v23.0.0 | No longer experimental. |
v22.1.0, v20.13.0 | CustomEvent is now stable. |
v19.0.0 | No longer behind --experimental-global-customevent CLI flag. |
v18.7.0, v16.17.0 | Added in: v18.7.0, v16.17.0 |
- 拡張: <Event>
CustomEvent
オブジェクトは、CustomEvent
Web API のアダプテーションです。インスタンスは Node.js によって内部的に作成されます。
event.detail
[History]
Version | Changes |
---|---|
v22.1.0, v20.13.0 | CustomEvent is now stable. |
v18.7.0, v16.17.0 | Added in: v18.7.0, v16.17.0 |
- タイプ: <any> 初期化時に渡されるカスタムデータを返します。
読み取り専用。
クラス: NodeEventTarget
追加: v14.5.0
- 拡張: <EventTarget>
NodeEventTarget
は、EventEmitter
API のサブセットをエミュレートする Node.js 固有の EventTarget
の拡張です。
nodeEventTarget.addListener(type, listener)
追加: v14.5.0
type
<string>listener
<Function> | <EventListener>- 戻り値: <EventTarget>
this
EventEmitter
API と同等のものをエミュレートする、EventTarget
クラスの Node.js 固有の拡張。 addListener()
と addEventListener()
の唯一の違いは、addListener()
が EventTarget
への参照を返すことです。
nodeEventTarget.emit(type, arg)
追加: v15.2.0
EventTarget
クラスの Node.js 固有の拡張で、type
のハンドラーのリストに arg
をディスパッチします。
nodeEventTarget.eventNames()
追加: v14.5.0
- 戻り値: <string[]>
イベントリスナーが登録されているイベントの type
名の配列を返す、EventTarget
クラスの Node.js 固有の拡張。
nodeEventTarget.listenerCount(type)
追加: v14.5.0
type
に登録されているイベントリスナーの数を返す、EventTarget
クラスの Node.js 固有の拡張。
nodeEventTarget.setMaxListeners(n)
Added in: v14.5.0
n
<number>
Node.js固有のEventTarget
クラスの拡張で、最大イベントリスナー数をn
として設定します。
nodeEventTarget.getMaxListeners()
Added in: v14.5.0
- 戻り値: <number>
Node.js固有のEventTarget
クラスの拡張で、最大イベントリスナー数を返します。
nodeEventTarget.off(type, listener[, options])
Added in: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
戻り値: <EventTarget> this
Node.js固有のeventTarget.removeEventListener()
のエイリアスです。
nodeEventTarget.on(type, listener)
Added in: v14.5.0
type
<string>listener
<Function> | <EventListener>- 戻り値: <EventTarget> this
Node.js固有のeventTarget.addEventListener()
のエイリアスです。
nodeEventTarget.once(type, listener)
Added in: v14.5.0
type
<string>listener
<Function> | <EventListener>- 戻り値: <EventTarget> this
Node.js固有のEventTarget
クラスの拡張で、指定されたイベントtype
に対してonce
リスナーを追加します。これは、once
オプションをtrue
に設定してon
を呼び出すことと同等です。
nodeEventTarget.removeAllListeners([type])
Added in: v14.5.0
type
<string>- 返します: <EventTarget> this
Node.js 固有の EventTarget
クラスの拡張です。type
が指定された場合、type
に登録されているすべてのリスナーを削除します。それ以外の場合は、登録されているすべてのリスナーを削除します。
nodeEventTarget.removeListener(type, listener[, options])
Added in: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
返します: <EventTarget> this
Node.js 固有の EventTarget
クラスの拡張で、指定された type
の listener
を削除します。removeListener()
と removeEventListener()
の唯一の違いは、removeListener()
が EventTarget
への参照を返すことです。