Skip to content

Ereignisse

[Stabil: 2 - Stabil]

Stabil: 2 Stabilität: 2 - Stabil

Quellcode: lib/events.js

Ein Großteil der Node.js-Kern-API basiert auf einer idiomatischen, asynchronen, ereignisgesteuerten Architektur, in der bestimmte Arten von Objekten (sogenannte "Emitter") benannte Ereignisse auslösen, die das Aufrufen von Function-Objekten ("Listener") verursachen.

Zum Beispiel: Ein net.Server-Objekt löst jedes Mal ein Ereignis aus, wenn sich ein Peer damit verbindet; ein fs.ReadStream löst ein Ereignis aus, wenn die Datei geöffnet wird; ein Stream löst ein Ereignis aus, wenn Daten zum Lesen verfügbar sind.

Alle Objekte, die Ereignisse auslösen, sind Instanzen der Klasse EventEmitter. Diese Objekte stellen eine Funktion eventEmitter.on() bereit, mit der eine oder mehrere Funktionen an benannte Ereignisse angehängt werden können, die vom Objekt ausgelöst werden. Typischerweise sind Ereignisnamen Zeichenketten in Camel-Case-Schreibweise, aber es kann jeder gültige JavaScript-Eigenschaftsschlüssel verwendet werden.

Wenn das EventEmitter-Objekt ein Ereignis auslöst, werden alle Funktionen, die an dieses bestimmte Ereignis angehängt sind, synchron aufgerufen. Alle von den aufgerufenen Listenern zurückgegebenen Werte werden ignoriert und verworfen.

Das folgende Beispiel zeigt eine einfache EventEmitter-Instanz mit einem einzelnen Listener. Die Methode eventEmitter.on() wird verwendet, um Listener zu registrieren, während die Methode eventEmitter.emit() verwendet wird, um das Ereignis auszulösen.

js
import { EventEmitter } from 'node:events';

class MyEmitter extends EventEmitter {}

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

class MyEmitter extends EventEmitter {}

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

Argumente und this an Listener übergeben

Die Methode eventEmitter.emit() ermöglicht die Übergabe einer beliebigen Menge von Argumenten an die Listener-Funktionen. Denken Sie daran, dass beim Aufruf einer gewöhnlichen Listener-Funktion das Standard-Keyword this absichtlich so gesetzt wird, dass es auf die EventEmitter-Instanz verweist, an die der Listener angehängt ist.

js
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');
js
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');

Es ist möglich, ES6-Pfeilfunktionen als Listener zu verwenden, aber wenn dies der Fall ist, verweist das Schlüsselwort this nicht mehr auf die EventEmitter-Instanz:

js
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');
js
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');

Asynchron vs. synchron

Der EventEmitter ruft alle Listener synchron in der Reihenfolge auf, in der sie registriert wurden. Dies gewährleistet die korrekte Reihenfolge der Ereignisse und hilft, Race-Conditions und Logikfehler zu vermeiden. Bei Bedarf können Listener-Funktionen mit den Methoden setImmediate() oder process.nextTick() in einen asynchronen Betriebsmodus wechseln:

js
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');
js
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');

Ereignisse nur einmal behandeln

Wenn ein Listener mit der Methode eventEmitter.on() registriert wird, wird dieser Listener jedes Mal aufgerufen, wenn das benannte Ereignis ausgelöst wird.

js
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
js
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

Mit der Methode eventEmitter.once() ist es möglich, einen Listener zu registrieren, der höchstens einmal für ein bestimmtes Ereignis aufgerufen wird. Sobald das Ereignis ausgelöst wurde, wird der Listener abgemeldet und dann aufgerufen.

js
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
js
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

Fehlerereignisse

Wenn innerhalb einer EventEmitter-Instanz ein Fehler auftritt, besteht die typische Aktion darin, ein 'error'-Ereignis auszugeben. Diese werden in Node.js als Sonderfälle behandelt.

Wenn ein EventEmitter nicht mindestens einen Listener für das 'error'-Ereignis registriert hat und ein 'error'-Ereignis ausgegeben wird, wird der Fehler geworfen, ein Stacktrace wird ausgegeben und der Node.js-Prozess wird beendet.

js
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Wirft einen Fehler und lässt Node.js abstürzen
js
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Wirft einen Fehler und lässt Node.js abstürzen

Um das Abstürzen des Node.js-Prozesses zu verhindern, kann das domain-Modul verwendet werden. (Beachten Sie jedoch, dass das node:domain-Modul als veraltet gilt.)

Als Best Practice sollten immer Listener für die 'error'-Ereignisse hinzugefügt werden.

js
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('Hoppla! Es gab einen Fehler');
});
myEmitter.emit('error', new Error('whoops!'));
// Gibt aus: Hoppla! Es gab einen Fehler
js
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('Hoppla! Es gab einen Fehler');
});
myEmitter.emit('error', new Error('whoops!'));
// Gibt aus: Hoppla! Es gab einen Fehler

Es ist möglich, 'error'-Ereignisse zu überwachen, ohne den ausgegebenen Fehler zu verarbeiten, indem ein Listener mit dem Symbol events.errorMonitor installiert wird.

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

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
  MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Wirft immer noch einen Fehler und lässt Node.js abstürzen
js
const { EventEmitter, errorMonitor } = require('node:events');

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
  MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Wirft immer noch einen Fehler und lässt Node.js abstürzen

Ablehnungen von Promises abfangen

Die Verwendung von async-Funktionen mit Event-Handlern ist problematisch, da dies im Falle einer ausgelösten Ausnahme zu einer unbehandelten Ablehnung führen kann:

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

Die Option captureRejections im EventEmitter-Konstruktor oder die globale Einstellung ändern dieses Verhalten und installieren einen .then(undefined, handler)-Handler auf dem Promise. Dieser Handler leitet die Ausnahme asynchron an die Symbol.for('nodejs.rejection')-Methode weiter, falls vorhanden, oder an den 'error'-Event-Handler, falls keiner vorhanden ist.

js
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;
js
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;

Wenn events.captureRejections = true gesetzt wird, ändert sich die Standardeinstellung für alle neuen Instanzen von EventEmitter.

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

Die 'error'-Events, die durch das captureRejections-Verhalten erzeugt werden, haben keinen Catch-Handler, um endlose Fehlerschleifen zu vermeiden: Die Empfehlung lautet, async-Funktionen nicht als 'error'-Event-Handler zu verwenden.

Klasse: EventEmitter

[Historie]

VersionÄnderungen
v13.4.0, v12.16.0Option captureRejections hinzugefügt.
v0.1.26Hinzugefügt in: v0.1.26

Die Klasse EventEmitter wird durch das Modul node:events definiert und bereitgestellt:

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

Alle EventEmitter senden das Ereignis 'newListener' aus, wenn neue Listener hinzugefügt werden, und 'removeListener', wenn vorhandene Listener entfernt werden.

Es unterstützt die folgende Option:

Ereignis: 'newListener'

Hinzugefügt in: v0.1.26

Die EventEmitter-Instanz löst ihr eigenes 'newListener'-Ereignis aus, bevor ein Listener zu ihrem internen Array von Listenern hinzugefügt wird.

Listener, die für das 'newListener'-Ereignis registriert sind, erhalten den Ereignisnamen und eine Referenz auf den Listener, der hinzugefügt wird.

Die Tatsache, dass das Ereignis vor dem Hinzufügen des Listeners ausgelöst wird, hat einen subtilen, aber wichtigen Nebeneffekt: Alle zusätzlichen Listener, die für denselben name innerhalb des 'newListener'-Callbacks registriert werden, werden vor dem Listener eingefügt, der gerade hinzugefügt wird.

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

const myEmitter = new MyEmitter();
// Nur einmal ausführen, damit wir nicht endlos schleifen
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Neuen Listener davor einfügen
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Ausgabe:
//   B
//   A
js
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
// Nur einmal ausführen, damit wir nicht endlos schleifen
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Neuen Listener davor einfügen
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Ausgabe:
//   B
//   A

Ereignis: 'removeListener'

[Verlauf]

VersionÄnderungen
v6.1.0, v4.7.0Für Listener, die mit .once() angehängt wurden, liefert das listener-Argument nun die ursprüngliche Listener-Funktion.
v0.9.3Hinzugefügt in: v0.9.3

Das Ereignis 'removeListener' wird nachdem der listener entfernt wurde, ausgelöst.

emitter.addListener(eventName, listener)

Hinzugefügt in: v0.1.26

Alias für emitter.on(eventName, listener).

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

Hinzugefügt in: v0.1.26

Ruft synchron jeden der für das Ereignis namens eventName registrierten Listener in der Reihenfolge auf, in der sie registriert wurden, und übergibt die bereitgestellten Argumente an jeden einzelnen.

Gibt true zurück, wenn das Ereignis Listener hatte, andernfalls false.

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

Hinzugefügt in: v6.0.0

Gibt ein Array zurück, das die Ereignisse auflistet, für die der Emitter Listener registriert hat. Die Werte im Array sind Strings oder Symbole.

js
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) ]
js
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()

Hinzugefügt in: v1.0.0

Gibt den aktuellen maximalen Listener-Wert für den EventEmitter zurück, der entweder durch emitter.setMaxListeners(n) gesetzt wurde oder standardmäßig auf events.defaultMaxListeners eingestellt ist.

emitter.listenerCount(eventName[, listener])

[Verlauf]

VersionÄnderungen
v19.8.0, v18.16.0Das listener-Argument wurde hinzugefügt.
v3.2.0Hinzugefügt in: v3.2.0

Gibt die Anzahl der Listener zurück, die auf das Ereignis mit dem Namen eventName warten. Wenn listener angegeben ist, wird zurückgegeben, wie oft der Listener in der Liste der Listener des Ereignisses gefunden wurde.

emitter.listeners(eventName)

[Historie]

VersionÄnderungen
v7.0.0Für Listener, die mit .once() hinzugefügt wurden, werden nun die ursprünglichen Listener anstelle von Wrapper-Funktionen zurückgegeben.
v0.1.26Hinzugefügt in: v0.1.26

Gibt eine Kopie des Arrays von Listenern für das Ereignis mit dem Namen eventName zurück.

js
server.on('connection', (stream) => {
  console.log('jemand hat sich verbunden!');
});
console.log(util.inspect(server.listeners('connection')));
// Gibt aus: [ [Function] ]

emitter.off(eventName, listener)

Hinzugefügt in: v10.0.0

Alias für emitter.removeListener().

emitter.on(eventName, listener)

Hinzugefügt in: v0.1.101

Fügt die listener-Funktion am Ende des Listener-Arrays für das Ereignis namens eventName hinzu. Es wird nicht geprüft, ob der listener bereits hinzugefügt wurde. Mehrere Aufrufe, die dieselbe Kombination aus eventName und listener übergeben, führen dazu, dass der listener mehrfach hinzugefügt und aufgerufen wird.

js
server.on('connection', (stream) => {
  console.log('jemand hat sich verbunden!');
});

Gibt eine Referenz zum EventEmitter zurück, sodass Aufrufe verkettet werden können.

Standardmäßig werden Ereignis-Listener in der Reihenfolge aufgerufen, in der sie hinzugefügt werden. Die Methode emitter.prependListener() kann alternativ verwendet werden, um den Ereignis-Listener am Anfang des Listener-Arrays hinzuzufügen.

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

emitter.once(eventName, listener)

Hinzugefügt in: v0.3.0

Fügt eine einmalige listener-Funktion für das Ereignis namens eventName hinzu. Das nächste Mal, wenn eventName ausgelöst wird, wird dieser Listener entfernt und dann aufgerufen.

js
server.once('connection', (stream) => {
  console.log('Ah, wir haben unseren ersten Benutzer!');
});

Gibt eine Referenz zum EventEmitter zurück, so dass Aufrufe verkettet werden können.

Standardmäßig werden Event-Listener in der Reihenfolge aufgerufen, in der sie hinzugefügt werden. Die Methode emitter.prependOnceListener() kann als Alternative verwendet werden, um den Event-Listener am Anfang des Listener-Arrays hinzuzufügen.

js
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
js
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)

Hinzugefügt in: v6.0.0

Fügt die listener-Funktion am Anfang des Listener-Arrays für das Ereignis namens eventName hinzu. Es werden keine Prüfungen durchgeführt, um festzustellen, ob der listener bereits hinzugefügt wurde. Mehrere Aufrufe, die die gleiche Kombination aus eventName und listener übergeben, führen dazu, dass der listener mehrfach hinzugefügt und aufgerufen wird.

js
server.prependListener('connection', (stream) => {
  console.log('jemand hat sich verbunden!');
});

Gibt eine Referenz zum EventEmitter zurück, so dass Aufrufe verkettet werden können.

emitter.prependOnceListener(eventName, listener)

Hinzugefügt in: v6.0.0

Fügt eine einmalige listener-Funktion für das Ereignis mit dem Namen eventName am Anfang des Listener-Arrays hinzu. Das nächste Mal, wenn eventName ausgelöst wird, wird dieser Listener entfernt und dann aufgerufen.

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

Gibt eine Referenz auf den EventEmitter zurück, sodass Aufrufe verkettet werden können.

emitter.removeAllListeners([eventName])

Hinzugefügt in: v0.1.26

Entfernt alle Listener oder die des angegebenen eventName.

Es ist schlechte Praxis, Listener zu entfernen, die an anderer Stelle im Code hinzugefügt wurden, insbesondere wenn die EventEmitter-Instanz von einer anderen Komponente oder einem anderen Modul erstellt wurde (z. B. Sockets oder File Streams).

Gibt eine Referenz auf den EventEmitter zurück, sodass Aufrufe verkettet werden können.

emitter.removeListener(eventName, listener)

Hinzugefügt in: v0.1.26

Entfernt den angegebenen listener aus dem Listener-Array für das Ereignis mit dem Namen eventName.

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

removeListener() entfernt maximal eine Instanz eines Listeners aus dem Listener-Array. Wenn ein einzelner Listener dem Listener-Array für das angegebene eventName mehrmals hinzugefügt wurde, muss removeListener() mehrmals aufgerufen werden, um jede Instanz zu entfernen.

Sobald ein Ereignis ausgelöst wird, werden alle daran zum Zeitpunkt der Auslösung angehängten Listener der Reihe nach aufgerufen. Dies impliziert, dass alle removeListener()- oder removeAllListeners()-Aufrufe nach dem Auslösen und vor dem Ende der Ausführung des letzten Listeners diese nicht von emit() in Bearbeitung entfernen. Nachfolgende Ereignisse verhalten sich wie erwartet.

js
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
js
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

Da Listener über ein internes Array verwaltet werden, ändert der Aufruf dieser Funktion die Positionsindizes aller Listener, die nach dem zu entfernenden Listener registriert wurden. Dies hat keine Auswirkungen auf die Reihenfolge, in der Listener aufgerufen werden, bedeutet jedoch, dass alle Kopien des Listener-Arrays, wie sie von der Methode emitter.listeners() zurückgegeben werden, neu erstellt werden müssen.

Wenn eine einzelne Funktion mehrmals als Handler für ein einzelnes Ereignis hinzugefügt wurde (wie im folgenden Beispiel), entfernt removeListener() die zuletzt hinzugefügte Instanz. Im Beispiel wird der once('ping')-Listener entfernt:

js
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');
js
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');

Gibt eine Referenz auf den EventEmitter zurück, sodass Aufrufe verkettet werden können.

emitter.setMaxListeners(n)

Hinzugefügt in: v0.3.5

Standardmäßig geben EventEmitters eine Warnung aus, wenn mehr als 10 Listener für ein bestimmtes Ereignis hinzugefügt werden. Dies ist ein nützlicher Standardwert, der hilft, Speicherlecks zu finden. Die Methode emitter.setMaxListeners() ermöglicht es, das Limit für diese spezifische EventEmitter-Instanz zu ändern. Der Wert kann auf Infinity (oder 0) gesetzt werden, um eine unbegrenzte Anzahl von Listenern anzugeben.

Gibt eine Referenz zum EventEmitter zurück, sodass Aufrufe verkettet werden können.

emitter.rawListeners(eventName)

Hinzugefügt in: v9.4.0

Gibt eine Kopie des Arrays von Listenern für das Ereignis namens eventName zurück, einschließlich aller Wrapper (wie z. B. die von .once() erstellten).

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

// Gibt ein neues Array mit einer Funktion `onceWrapper` zurück, die eine Eigenschaft
// `listener` hat, die den oben gebundenen ursprünglichen Listener enthält
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Protokolliert "log once" in der Konsole und entbindet das `once`-Ereignis nicht
logFnWrapper.listener();

// Protokolliert "log once" in der Konsole und entfernt den Listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Gibt ein neues Array mit einer einzelnen Funktion zurück, die oben durch `.on()` gebunden wurde
const newListeners = emitter.rawListeners('log');

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

// Gibt ein neues Array mit einer Funktion `onceWrapper` zurück, die eine Eigenschaft
// `listener` hat, die den oben gebundenen ursprünglichen Listener enthält
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Protokolliert "log once" in der Konsole und entbindet das `once`-Ereignis nicht
logFnWrapper.listener();

// Protokolliert "log once" in der Konsole und entfernt den Listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Gibt ein neues Array mit einer einzelnen Funktion zurück, die oben durch `.on()` gebunden wurde
const newListeners = emitter.rawListeners('log');

// Protokolliert "log persistently" zweimal
newListeners[0]();
emitter.emit('log');

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

[Historie]

VersionÄnderungen
v17.4.0, v16.14.0Nicht mehr experimentell.
v13.4.0, v12.16.0Hinzugefügt in: v13.4.0, v12.16.0

Die Symbol.for('nodejs.rejection')-Methode wird aufgerufen, wenn eine Promise-Ablehnung auftritt, wenn ein Ereignis ausgelöst wird und captureRejections auf dem Emitter aktiviert ist. Es ist möglich, events.captureRejectionSymbol anstelle von Symbol.for('nodejs.rejection') zu verwenden.

js
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.
  }
}
js
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

Hinzugefügt in: v0.11.2

Standardmäßig können maximal 10 Listener für jedes einzelne Ereignis registriert werden. Dieses Limit kann für einzelne EventEmitter-Instanzen mithilfe der Methode emitter.setMaxListeners(n) geändert werden. Um den Standardwert für alle EventEmitter-Instanzen zu ändern, kann die Eigenschaft events.defaultMaxListeners verwendet werden. Wenn dieser Wert keine positive Zahl ist, wird ein RangeError ausgelöst.

Seien Sie vorsichtig beim Festlegen von events.defaultMaxListeners, da die Änderung alle EventEmitter-Instanzen betrifft, einschließlich derer, die vor der Änderung erstellt wurden. Der Aufruf von emitter.setMaxListeners(n) hat jedoch weiterhin Vorrang vor events.defaultMaxListeners.

Dies ist keine harte Grenze. Die EventEmitter-Instanz erlaubt das Hinzufügen weiterer Listener, gibt aber eine Trace-Warnung an stderr aus, die darauf hinweist, dass ein "möglicher EventEmitter-Memory-Leak" erkannt wurde. Für jeden einzelnen EventEmitter können die Methoden emitter.getMaxListeners() und emitter.setMaxListeners() verwendet werden, um diese Warnung vorübergehend zu vermeiden:

defaultMaxListeners hat keine Auswirkung auf AbortSignal-Instanzen. Obwohl es immer noch möglich ist, emitter.setMaxListeners(n) zu verwenden, um eine Warnungsgrenze für einzelne AbortSignal-Instanzen festzulegen, warnen AbortSignal-Instanzen standardmäßig nicht.

js
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));
});
js
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));
});

Das Befehlszeilenflag --trace-warnings kann verwendet werden, um den Stack-Trace für solche Warnungen anzuzeigen.

Die ausgegebene Warnung kann mit process.on('warning') untersucht werden und hat die zusätzlichen Eigenschaften emitter, type und count, die sich auf die Event-Emitter-Instanz, den Namen des Ereignisses bzw. die Anzahl der angehängten Listener beziehen. Die Eigenschaft name ist auf 'MaxListenersExceededWarning' gesetzt.

events.errorMonitor

Hinzugefügt in: v13.6.0, v12.17.0

Dieses Symbol sollte verwendet werden, um einen Listener nur zur Überwachung von 'error'-Ereignissen zu installieren. Listener, die mit diesem Symbol installiert werden, werden aufgerufen, bevor die regulären 'error'-Listener aufgerufen werden.

Die Installation eines Listeners mit diesem Symbol ändert das Verhalten nicht, sobald ein 'error'-Ereignis ausgelöst wird. Daher stürzt der Prozess weiterhin ab, wenn kein regulärer 'error'-Listener installiert ist.

events.getEventListeners(emitterOrTarget, eventName)

Hinzugefügt in: v15.2.0, v14.17.0

Gibt eine Kopie des Arrays von Listenern für das Ereignis mit dem Namen eventName zurück.

Für EventEmitter verhält sich dies genau so, wie wenn .listeners auf dem Emitter aufgerufen wird.

Für EventTarget ist dies die einzige Möglichkeit, die Ereignis-Listener für das Ereignis-Ziel zu erhalten. Dies ist nützlich für Debugging- und Diagnosezwecke.

js
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] ]
}
js
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)

Hinzugefügt in: v19.9.0, v18.17.0

Gibt die aktuell eingestellte maximale Anzahl von Listenern zurück.

Für EventEmitter verhält sich dies genau so, als würde man .getMaxListeners auf dem Emitter aufrufen.

Für EventTarget ist dies die einzige Möglichkeit, die maximale Anzahl von Event-Listenern für das Event-Ziel zu erhalten. Wenn die Anzahl der Event-Handler für ein einzelnes EventTarget das Maximum überschreitet, gibt das EventTarget eine Warnung aus.

js
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
}
js
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])

[Verlauf]

VersionÄnderungen
v15.0.0Die Option signal wird jetzt unterstützt.
v11.13.0, v10.16.0Hinzugefügt in: v11.13.0, v10.16.0

Erstellt eine Promise, die erfüllt wird, wenn der EventEmitter das angegebene Ereignis auslöst, oder die abgelehnt wird, wenn der EventEmitter während des Wartens 'error' auslöst. Die Promise wird mit einem Array aller Argumente aufgelöst, die an das angegebene Ereignis ausgegeben werden.

Diese Methode ist absichtlich generisch und funktioniert mit der Webplattform EventTarget-Schnittstelle, die keine spezielle 'error'-Ereignissemantik hat und nicht auf das 'error'-Ereignis hört.

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

Die spezielle Behandlung des Ereignisses 'error' wird nur verwendet, wenn events.once() verwendet wird, um auf ein anderes Ereignis zu warten. Wenn events.once() verwendet wird, um auf das Ereignis 'error' selbst zu warten, wird es wie jede andere Art von Ereignis ohne spezielle Behandlung behandelt:

js
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
js
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

Ein <AbortSignal> kann verwendet werden, um das Warten auf das Ereignis abzubrechen:

js
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!
js
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!

Warten auf mehrere Ereignisse, die auf process.nextTick() ausgelöst werden

Es gibt einen Sonderfall, der beachtet werden sollte, wenn die Funktion events.once() verwendet wird, um auf mehrere Ereignisse zu warten, die im selben Batch von process.nextTick()-Operationen oder immer dann ausgelöst werden, wenn mehrere Ereignisse synchron ausgelöst werden. Da die process.nextTick()-Warteschlange vor der Promise-Microtask-Warteschlange geleert wird und EventEmitter alle Ereignisse synchron auslöst, ist es möglich, dass events.once() ein Ereignis verpasst.

js
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');

  // Dieses Promise wird niemals aufgelöst, da das 'foo'-Ereignis bereits
  // ausgelöst wurde, bevor das Promise erstellt wurde.
  await once(myEE, 'foo');
  console.log('foo');
}

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

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

const myEE = new EventEmitter();

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

  // Dieses Promise wird niemals aufgelöst, da das 'foo'-Ereignis bereits
  // ausgelöst wurde, bevor das Promise erstellt wurde.
  await once(myEE, 'foo');
  console.log('foo');
}

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

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

Um beide Ereignisse abzufangen, erstellen Sie jedes der Promises bevor Sie auf eines von beiden warten. Dann wird es möglich, Promise.all(), Promise.race() oder Promise.allSettled() zu verwenden:

js
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'));
js
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

[Verlauf]

VersionÄnderungen
v17.4.0, v16.14.0Nicht mehr experimentell.
v13.4.0, v12.16.0Hinzugefügt in: v13.4.0, v12.16.0

Wert: <boolean>

Ändert die Standardoption captureRejections für alle neuen EventEmitter-Objekte.

events.captureRejectionSymbol

[Verlauf]

VersionÄnderungen
v17.4.0, v16.14.0Nicht mehr experimentell.
v13.4.0, v12.16.0Hinzugefügt in: v13.4.0, v12.16.0

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

Siehe, wie man einen benutzerdefinierten Rejection-Handler schreibt.

events.listenerCount(emitter, eventName)

Hinzugefügt in: v0.9.12

Veraltet seit: v3.2.0

[Stabil: 0 - Veraltet]

Stabil: 0 Stabilität: 0 - Veraltet: Verwenden Sie stattdessen emitter.listenerCount().

Eine Klassenmethode, die die Anzahl der Listener für den gegebenen eventName zurückgibt, die auf dem gegebenen emitter registriert sind.

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

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

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

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

[Verlauf]

VersionÄnderungen
v22.0.0, v20.13.0Unterstützung für highWaterMark- und lowWaterMark-Optionen, zur Konsistenz. Alte Optionen werden weiterhin unterstützt.
v20.0.0Die Optionen close, highWatermark und lowWatermark werden jetzt unterstützt.
v13.6.0, v12.16.0Hinzugefügt in: v13.6.0, v12.16.0
  • emitter <EventEmitter>

  • eventName <string> | <symbol> Der Name des Ereignisses, auf das gewartet wird

  • options <Object>

    • signal <AbortSignal> Kann verwendet werden, um das Warten auf Ereignisse abzubrechen.
    • close - <string[]> Namen von Ereignissen, die die Iteration beenden.
    • highWaterMark - <integer> Standard: Number.MAX_SAFE_INTEGER Der High Watermark Wert. Der Emitter wird jedes Mal angehalten, wenn die Größe der gepufferten Ereignisse höher ist als dieser Wert. Wird nur von Emittern unterstützt, die die Methoden pause() und resume() implementieren.
    • lowWaterMark - <integer> Standard: 1 Der Low Watermark Wert. Der Emitter wird jedes Mal fortgesetzt, wenn die Größe der gepufferten Ereignisse niedriger ist als dieser Wert. Wird nur von Emittern unterstützt, die die Methoden pause() und resume() implementieren.
  • Gibt zurück: <AsyncIterator>, der eventName-Ereignisse iteriert, die vom emitter ausgegeben werden

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

const ee = new EventEmitter();

// Später ausgeben
process.nextTick(() => {
  ee.emit('foo', 'bar');
  ee.emit('foo', 42);
});

for await (const event of on(ee, 'foo')) {
  // Die Ausführung dieses inneren Blocks ist synchron und er
  // verarbeitet jeweils ein Ereignis (auch mit await). Nicht verwenden,
  // wenn eine gleichzeitige Ausführung erforderlich ist.
  console.log(event); // gibt ['bar'] [42] aus
}
// Hier nicht erreichbar
js
const { on, EventEmitter } = require('node:events');

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

  // Später ausgeben
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo')) {
    // Die Ausführung dieses inneren Blocks ist synchron und er
    // verarbeitet jeweils ein Ereignis (auch mit await). Nicht verwenden,
    // wenn eine gleichzeitige Ausführung erforderlich ist.
    console.log(event); // gibt ['bar'] [42] aus
  }
  // Hier nicht erreichbar
})();

Gibt einen AsyncIterator zurück, der eventName-Ereignisse iteriert. Es wird ein Fehler ausgegeben, wenn der EventEmitter 'error' ausgibt. Es entfernt alle Listener beim Verlassen der Schleife. Der von jeder Iteration zurückgegebene value ist ein Array, das aus den ausgegebenen Ereignisargumenten besteht.

Ein <AbortSignal> kann verwendet werden, um das Warten auf Ereignisse abzubrechen:

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

const ac = new AbortController();

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

  // Später ausgeben
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo', { signal: ac.signal })) {
    // Die Ausführung dieses inneren Blocks ist synchron und er
    // verarbeitet jeweils ein Ereignis (auch mit await). Nicht verwenden,
    // wenn eine gleichzeitige Ausführung erforderlich ist.
    console.log(event); // gibt ['bar'] [42] aus
  }
  // Hier nicht erreichbar
})();

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

const ac = new AbortController();

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

  // Später ausgeben
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo', { signal: ac.signal })) {
    // Die Ausführung dieses inneren Blocks ist synchron und er
    // verarbeitet jeweils ein Ereignis (auch mit await). Nicht verwenden,
    // wenn eine gleichzeitige Ausführung erforderlich ist.
    console.log(event); // gibt ['bar'] [42] aus
  }
  // Hier nicht erreichbar
})();

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

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

Hinzugefügt in: v15.4.0

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

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

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

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

setMaxListeners(5, target, emitter);

events.addAbortListener(signal, listener)

Hinzugefügt in: v20.5.0, v18.18.0

[Stable: 1 - Experimental]

Stable: 1 Stabilität: 1 - Experimentell

Hört einmalig auf das abort-Ereignis des bereitgestellten signal.

Das Abhören des abort-Ereignisses auf Abort-Signalen ist unsicher und kann zu Ressourcenlecks führen, da ein anderer Dritter mit dem Signal e.stopImmediatePropagation() aufrufen kann. Leider kann Node.js dies nicht ändern, da dies gegen den Webstandard verstoßen würde. Darüber hinaus macht es die ursprüngliche API leicht, das Entfernen von Listenern zu vergessen.

Diese API ermöglicht die sichere Verwendung von AbortSignals in Node.js-APIs, indem diese beiden Probleme gelöst werden, indem das Ereignis so abgehört wird, dass stopImmediatePropagation nicht verhindert, dass der Listener ausgeführt wird.

Gibt ein Disposable zurück, damit es leichter abgemeldet werden kann.

js
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]();
  }
}
js
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]();
  }
}

Klasse: events.EventEmitterAsyncResource extends EventEmitter

Hinzugefügt in: v17.4.0, v16.14.0

Integriert EventEmitter mit <AsyncResource> für EventEmitter, die eine manuelle Async-Verfolgung benötigen. Insbesondere werden alle Ereignisse, die von Instanzen von events.EventEmitterAsyncResource emittiert werden, innerhalb ihres Async-Kontexts ausgeführt.

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

// Async-Tracking-Tools identifizieren dies als 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });

// 'foo'-Listener werden im Async-Kontext des EventEmitters ausgeführt.
ee1.on('foo', () => {
  strictEqual(executionAsyncId(), ee1.asyncId);
  strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});

const ee2 = new EventEmitter();

// 'foo'-Listener auf gewöhnlichen EventEmittern, die keinen Async-
// Kontext verfolgen, werden jedoch im selben Async-Kontext wie emit() ausgeführt.
ee2.on('foo', () => {
  notStrictEqual(executionAsyncId(), ee2.asyncId);
  notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});

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

// Async-Tracking-Tools identifizieren dies als 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });

// 'foo'-Listener werden im Async-Kontext des EventEmitters ausgeführt.
ee1.on('foo', () => {
  strictEqual(executionAsyncId(), ee1.asyncId);
  strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});

const ee2 = new EventEmitter();

// 'foo'-Listener auf gewöhnlichen EventEmittern, die keinen Async-
// Kontext verfolgen, werden jedoch im selben Async-Kontext wie emit() ausgeführt.
ee2.on('foo', () => {
  notStrictEqual(executionAsyncId(), ee2.asyncId);
  notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});

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

Die Klasse EventEmitterAsyncResource hat die gleichen Methoden und nimmt die gleichen Optionen wie EventEmitter und AsyncResource selbst entgegen.

new events.EventEmitterAsyncResource([options])

  • options <Object>
    • captureRejections <boolean> Aktiviert das automatische Erfassen von Promise-Ablehnungen. Standard: false.
    • name <string> Der Typ des asynchronen Ereignisses. Standard: new.target.name.
    • triggerAsyncId <number> Die ID des Ausführungskontextes, der dieses asynchrone Ereignis erzeugt hat. Standard: executionAsyncId().
    • requireManualDestroy <boolean> Wenn auf true gesetzt, deaktiviert emitDestroy, wenn das Objekt vom Garbage Collector erfasst wird. Dies muss normalerweise nicht gesetzt werden (auch wenn emitDestroy manuell aufgerufen wird), es sei denn, die asyncId der Ressource wird abgerufen und die sensible API emitDestroy wird damit aufgerufen. Wenn auf false gesetzt, erfolgt der emitDestroy-Aufruf bei der Garbage Collection nur, wenn mindestens ein aktiver destroy-Hook vorhanden ist. Standard: false.

eventemitterasyncresource.asyncId

  • Typ: <number> Die eindeutige asyncId, die der Ressource zugewiesen wurde.

eventemitterasyncresource.asyncResource

Das zurückgegebene AsyncResource-Objekt hat eine zusätzliche eventEmitter-Eigenschaft, die einen Verweis auf diese EventEmitterAsyncResource bereitstellt.

eventemitterasyncresource.emitDestroy()

Ruft alle destroy-Hooks auf. Dies sollte nur einmal aufgerufen werden. Es wird ein Fehler geworfen, wenn es mehr als einmal aufgerufen wird. Dies muss manuell aufgerufen werden. Wenn die Ressource der GC überlassen wird, werden die destroy-Hooks niemals aufgerufen.

eventemitterasyncresource.triggerAsyncId

  • Typ: <number> Die gleiche triggerAsyncId, die dem AsyncResource-Konstruktor übergeben wird.

EventTarget- und Event-API

[Verlauf]

VersionÄnderungen
v16.0.0EventTarget-Fehlerbehandlung geändert.
v15.4.0Nicht mehr experimentell.
v15.0.0Die Klassen EventTarget und Event sind jetzt als Globale verfügbar.
v14.5.0Hinzugefügt in: v14.5.0

Die Objekte EventTarget und Event sind eine Node.js-spezifische Implementierung der EventTarget Web API, die von einigen Node.js-Kern-APIs bereitgestellt werden.

js
const target = new EventTarget();

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

Node.js EventTarget vs. DOM EventTarget

Es gibt zwei Hauptunterschiede zwischen dem Node.js EventTarget und der EventTarget Web API:

NodeEventTarget vs. EventEmitter

Das NodeEventTarget-Objekt implementiert eine modifizierte Teilmenge der EventEmitter-API, die es ihm ermöglicht, einen EventEmitter in bestimmten Situationen genau zu emulieren. Ein NodeEventTarget ist keine Instanz von EventEmitter und kann in den meisten Fällen nicht anstelle eines EventEmitter verwendet werden.

Event-Listener

Event-Listener, die für einen Event type registriert sind, können entweder JavaScript-Funktionen oder Objekte mit einer handleEvent-Eigenschaft sein, deren Wert eine Funktion ist.

In jedem Fall wird die Handler-Funktion mit dem event-Argument aufgerufen, das der Funktion eventTarget.dispatchEvent() übergeben wird.

Asynchrone Funktionen können als Event-Listener verwendet werden. Wenn eine asynchrone Handler-Funktion ablehnt, wird die Ablehnung erfasst und wie in EventTarget-Fehlerbehandlung beschrieben behandelt.

Ein von einer Handler-Funktion ausgelöster Fehler verhindert nicht, dass die anderen Handler aufgerufen werden.

Der Rückgabewert einer Handler-Funktion wird ignoriert.

Handler werden immer in der Reihenfolge aufgerufen, in der sie hinzugefügt wurden.

Handler-Funktionen können das event-Objekt mutieren.

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

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

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

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

const target = new EventTarget();

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

Fehlerbehandlung in EventTarget

Wenn ein registrierter Event-Listener eine Ausnahme auslöst (oder ein Promise zurückgibt, das abgelehnt wird), wird der Fehler standardmäßig als unbehandelte Ausnahme in process.nextTick() behandelt. Dies bedeutet, dass unbehandelte Ausnahmen in EventTargets standardmäßig den Node.js-Prozess beenden.

Das Auslösen innerhalb eines Event-Listeners verhindert nicht, dass die anderen registrierten Handler aufgerufen werden.

Das EventTarget implementiert keine spezielle Standardbehandlung für Ereignisse vom Typ 'error' wie EventEmitter.

Derzeit werden Fehler zuerst an das process.on('error')-Ereignis weitergeleitet, bevor sie process.on('uncaughtException') erreichen. Dieses Verhalten ist veraltet und wird sich in einer zukünftigen Version ändern, um EventTarget an andere Node.js-APIs anzugleichen. Jeder Code, der sich auf das process.on('error')-Ereignis verlässt, sollte an das neue Verhalten angepasst werden.

Klasse: Event

[Historie]

VersionÄnderungen
v15.0.0Die Klasse Event ist jetzt über das globale Objekt verfügbar.
v14.5.0Hinzugefügt in: v14.5.0

Das Event-Objekt ist eine Adaption der Event Web API. Instanzen werden intern von Node.js erstellt.

event.bubbles

Hinzugefügt in: v14.5.0

Dies wird in Node.js nicht verwendet und wird nur der Vollständigkeit halber bereitgestellt.

event.cancelBubble

Hinzugefügt in: v14.5.0

[Stabil: 3 - Legacy]

Stabil: 3 Stabilität: 3 - Legacy: Verwenden Sie stattdessen event.stopPropagation().

Alias für event.stopPropagation(), wenn auf true gesetzt. Dies wird in Node.js nicht verwendet und wird nur der Vollständigkeit halber bereitgestellt.

event.cancelable

Hinzugefügt in: v14.5.0

  • Typ: <boolean> True, wenn das Ereignis mit der Option cancelable erstellt wurde.

event.composed

Hinzugefügt in: v14.5.0

Dies wird in Node.js nicht verwendet und dient nur der Vollständigkeit halber.

event.composedPath()

Hinzugefügt in: v14.5.0

Gibt ein Array zurück, das das aktuelle EventTarget als einzigen Eintrag enthält, oder leer ist, wenn das Ereignis nicht ausgelöst wird. Dies wird in Node.js nicht verwendet und dient nur der Vollständigkeit halber.

event.currentTarget

Hinzugefügt in: v14.5.0

Alias für event.target.

event.defaultPrevented

Hinzugefügt in: v14.5.0

Ist true, wenn cancelable true ist und event.preventDefault() aufgerufen wurde.

event.eventPhase

Hinzugefügt in: v14.5.0

  • Typ: <number> Gibt 0 zurück, solange ein Ereignis nicht ausgelöst wird, 2, solange es ausgelöst wird.

Dies wird in Node.js nicht verwendet und dient nur der Vollständigkeit halber.

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

Hinzugefügt in: v19.5.0

[Stabil: 3 - Legacy]

Stabil: 3 Stabilität: 3 - Legacy: Die WHATWG-Spezifikation betrachtet sie als veraltet und Benutzer sollten sie überhaupt nicht verwenden.

Redundant mit Ereigniskonstruktoren und unfähig, composed zu setzen. Dies wird in Node.js nicht verwendet und dient nur der Vollständigkeit halber.

event.isTrusted

Hinzugefügt in: v14.5.0

Das <AbortSignal> "abort"-Ereignis wird mit isTrusted auf true gesetzt emittiert. In allen anderen Fällen ist der Wert false.

event.preventDefault()

Hinzugefügt in: v14.5.0

Setzt die Eigenschaft defaultPrevented auf true, wenn cancelable true ist.

event.returnValue

Hinzugefügt in: v14.5.0

[Stabil: 3 - Legacy]

Stabil: 3 Stabilität: 3 - Legacy: Verwenden Sie stattdessen event.defaultPrevented.

  • Typ: <boolean> True, wenn das Ereignis nicht abgebrochen wurde.

Der Wert von event.returnValue ist immer das Gegenteil von event.defaultPrevented. Dies wird in Node.js nicht verwendet und dient lediglich der Vollständigkeit halber.

event.srcElement

Hinzugefügt in: v14.5.0

[Stabil: 3 - Legacy]

Stabil: 3 Stabilität: 3 - Legacy: Verwenden Sie stattdessen event.target.

Alias für event.target.

event.stopImmediatePropagation()

Hinzugefügt in: v14.5.0

Stoppt den Aufruf von Event-Listenern, nachdem der aktuelle abgeschlossen ist.

event.stopPropagation()

Hinzugefügt in: v14.5.0

Dies wird in Node.js nicht verwendet und dient lediglich der Vollständigkeit halber.

event.target

Hinzugefügt in: v14.5.0

event.timeStamp

Hinzugefügt in: v14.5.0

Der Millisekunden-Zeitstempel, als das Event-Objekt erstellt wurde.

event.type

Hinzugefügt in: v14.5.0

Die Ereignistyp-Kennung.

Klasse: EventTarget

[Verlauf]

VersionÄnderungen
v15.0.0Die Klasse EventTarget ist jetzt über das globale Objekt verfügbar.
v14.5.0Hinzugefügt in: v14.5.0

eventTarget.addEventListener(type, listener[, options])

[Verlauf]

VersionÄnderungen
v15.4.0Unterstützung für die Option signal hinzugefügt.
v14.5.0Hinzugefügt in: v14.5.0
  • type <string>
  • listener <Function> | <EventListener>
  • options <Object>
    • once <boolean> Wenn true, wird der Listener automatisch entfernt, wenn er das erste Mal aufgerufen wird. Standard: false.
    • passive <boolean> Wenn true, dient dies als Hinweis darauf, dass der Listener nicht die Methode preventDefault() des Event-Objekts aufrufen wird. Standard: false.
    • capture <boolean> Wird von Node.js nicht direkt verwendet. Für API-Vollständigkeit hinzugefügt. Standard: false.
    • signal <AbortSignal> Der Listener wird entfernt, wenn die abort()-Methode des gegebenen AbortSignal-Objekts aufgerufen wird.

Fügt einen neuen Handler für das type-Ereignis hinzu. Jeder angegebene listener wird nur einmal pro type und pro capture-Optionswert hinzugefügt.

Wenn die Option once true ist, wird der listener entfernt, nachdem ein type-Ereignis das nächste Mal ausgelöst wurde.

Die Option capture wird von Node.js in keiner funktionalen Weise verwendet, außer zum Verfolgen registrierter Ereignis-Listener gemäß der EventTarget-Spezifikation. Insbesondere wird die Option capture als Teil des Schlüssels verwendet, wenn ein listener registriert wird. Jeder einzelne listener kann einmal mit capture = false und einmal mit capture = true hinzugefügt werden.

js
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)

Hinzugefügt in: v14.5.0

  • event <Event>
  • Gibt zurück: <boolean> true, wenn entweder das Attribut cancelable des Ereignisses den Wert false hat oder seine Methode preventDefault() nicht aufgerufen wurde, andernfalls false.

Sendet das event an die Liste der Handler für event.type.

Die registrierten Event-Listener werden synchron in der Reihenfolge aufgerufen, in der sie registriert wurden.

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

Hinzugefügt in: v14.5.0

Entfernt den listener aus der Liste der Handler für das Ereignis type.

Klasse: CustomEvent

[Verlauf]

VersionÄnderungen
v23.0.0Nicht mehr experimentell.
v22.1.0, v20.13.0CustomEvent ist jetzt stabil.
v19.0.0Nicht mehr hinter dem --experimental-global-customevent CLI-Flag.
v18.7.0, v16.17.0Hinzugefügt in: v18.7.0, v16.17.0

[Stabil: 2 - Stabil]

Stabil: 2 Stabilität: 2 - Stabil

Das CustomEvent-Objekt ist eine Anpassung der CustomEvent Web API. Instanzen werden intern von Node.js erstellt.

event.detail

[Verlauf]

VersionÄnderungen
v22.1.0, v20.13.0CustomEvent ist jetzt stabil.
v18.7.0, v16.17.0Hinzugefügt in: v18.7.0, v16.17.0

[Stabil: 2 - Stabil]

Stabil: 2 Stabilität: 2 - Stabil

  • Typ: <any> Gibt benutzerdefinierte Daten zurück, die bei der Initialisierung übergeben wurden.

Nur-Lesen.

Klasse: NodeEventTarget

Hinzugefügt in: v14.5.0

Das NodeEventTarget ist eine Node.js-spezifische Erweiterung zu EventTarget, die eine Teilmenge der EventEmitter-API emuliert.

nodeEventTarget.addListener(type, listener)

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der Klasse EventTarget, die die äquivalente EventEmitter-API emuliert. Der einzige Unterschied zwischen addListener() und addEventListener() besteht darin, dass addListener() eine Referenz auf das EventTarget zurückgibt.

nodeEventTarget.emit(type, arg)

Hinzugefügt in: v15.2.0

  • type <string>
  • arg <any>
  • Gibt zurück: <boolean> true, wenn Ereignis-Listener für den type registriert sind, andernfalls false.

Node.js-spezifische Erweiterung der Klasse EventTarget, die das arg an die Liste der Handler für type verteilt.

nodeEventTarget.eventNames()

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der Klasse EventTarget, die ein Array von Ereignis-type-Namen zurückgibt, für die Ereignis-Listener registriert sind.

nodeEventTarget.listenerCount(type)

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der Klasse EventTarget, die die Anzahl der Ereignis-Listener zurückgibt, die für den type registriert sind.

nodeEventTarget.setMaxListeners(n)

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der Klasse EventTarget, die die Anzahl der maximalen Event-Listener auf n setzt.

nodeEventTarget.getMaxListeners()

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der Klasse EventTarget, die die Anzahl der maximalen Event-Listener zurückgibt.

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

Hinzugefügt in: v14.5.0

Node.js-spezifischer Alias für eventTarget.removeEventListener().

nodeEventTarget.on(type, listener)

Hinzugefügt in: v14.5.0

Node.js-spezifischer Alias für eventTarget.addEventListener().

nodeEventTarget.once(type, listener)

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der Klasse EventTarget, die einen once-Listener für den angegebenen Event-type hinzufügt. Dies entspricht dem Aufruf von on mit der Option once auf true gesetzt.

nodeEventTarget.removeAllListeners([type])

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der EventTarget-Klasse. Wenn type angegeben ist, werden alle registrierten Listener für type entfernt, andernfalls werden alle registrierten Listener entfernt.

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

Hinzugefügt in: v14.5.0

Node.js-spezifische Erweiterung der EventTarget-Klasse, die den listener für den gegebenen type entfernt. Der einzige Unterschied zwischen removeListener() und removeEventListener() besteht darin, dass removeListener() eine Referenz auf das EventTarget zurückgibt.