Node.js EventEmitter

Alle asynchronen I/O-Operationen in Node.js senden nach Abschluss ein Ereignis an die Ereigniswarteschlange.

Viele Objekte in Node.js emittieren Ereignisse: Ein net.Server-Objekt emittiert jedes Mal ein Ereignis, wenn eine neue Verbindung aufgebaut wird, und ein fs.readStream-Objekt emittiert ein Ereignis, wenn eine Datei geöffnet wird. Alle diese Objekte, die Ereignisse erzeugen, sind Instanzen von events.EventEmitter.

EventEmitter ist ein Kernmodul in Node.js, das zum Erstellen, Registrieren und Auslösen von Ereignissen verwendet wird.

EventEmitter ist die Grundlage der ereignisgesteuerten Programmierung und hilft Entwicklern, Mechanismen zur Veröffentlichung und zum Abonnieren von Ereignissen einfach zu implementieren.


EventEmitter-Klasse

Das events-Modul stellt nur ein Objekt bereit: events.EventEmitter.

Der Kern von EventEmitter ist die Kapselung der Ereignisauslösung und der Ereignis-Listener-Funktionalität.

Du kannstrequire("events");verwenden, um auf dieses Modul zuzugreifen.

Beispiel

// Importiere das events-Modul
var events = require('events');
// Erstelle ein eventEmitter-Objekt
var eventEmitter = new events.EventEmitter();

Wenn beim Instanziieren eines EventEmitter-Objekts ein Fehler auftritt, wird das error-Ereignis ausgelöst. Das newListener-Ereignis wird ausgelöst, wenn ein neuer Listener hinzugefügt wird, und das removeListener-Ereignis wird ausgelöst, wenn ein Listener entfernt wird.

Im Folgenden verwenden wir ein einfaches Beispiel, um die Verwendung von EventEmitter zu veranschaulichen:

Beispiel

//event.js-Datei
var EventEmitter = require('events').EventEmitter;
var event = new EventEmitter();
event.on('some_event', function() {
        console.log('some_event-Ereignis ausgelöst');
});
setTimeout(function() {
        event.emit('some_event');
}, 1000);

Nach dem Ausführen dieses Codes gibt die Konsole nach 1 Sekunde Folgendes aus:some_event-Ereignis ausgelöstDas Prinzip ist, dass das event-Objekt einen Listener für das some_event-Ereignis registriert. Dann senden wir nach 1000 Millisekunden das some_event-Ereignis über setTimeout an das event-Objekt, woraufhin der some_event-Listener aufgerufen wird.

Das Ausführungsergebnis ist wie folgt:

$ node event.js 
some_event 事件触发

Jedes EventEmitter-Ereignis besteht aus einem Ereignisnamen und mehreren Parametern. Der Ereignisname ist eine Zeichenkette, die normalerweise eine bestimmte Bedeutung ausdrückt. Für jedes Ereignis unterstützt EventEmitter mehrere Ereignis-Listener.

Wenn ein Ereignis ausgelöst wird, werden die für dieses Ereignis registrierten Ereignis-Listener der Reihenfolge nach aufgerufen, und die Ereignisparameter werden als Argumente an die Callback-Funktion übergeben.

Lassen Sie uns diesen Prozess anhand des folgenden Beispiels erklären:

Beispiel

//event.js-Datei
var events = require('events');
var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
        console.log('listener1', arg1, arg2);
});
emitter.on('someEvent', function(arg1, arg2) {
        console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 parameter', 'arg2 parameter');

Das Ausführen des obigen Codes liefert das folgende Ergebnis:

$ node event.js 
listener1 arg1 参数 arg2 参数
listener2 arg1 参数 arg2 参数

Im obigen Beispiel registriert emitter zwei Ereignis-Listener für das Ereignis someEvent und löst dann das Ereignis someEvent aus.

Anhand des Ausführungsergebnisses können Sie sehen, dass die beiden Callback-Funktionen der Event-Listener nacheinander aufgerufen werden. Dies ist die einfachste Verwendung von EventEmitter.

EventEmitter bietet mehrere Eigenschaften, wie zum Beispielonundemit。oneine Funktion zum Binden von Event-Handlern,emitund eine Eigenschaft zum Auslösen eines Ereignisses. Als Nächstes sehen wir uns die EventEmitter-Eigenschaften genauer an.

Methoden

Nein.Methode & Beschreibung
1addListener(event, listener)
Fügt einen Listener für das angegebene Ereignis am Ende des Listener-Arrays hinzu.
2on(event, listener)
Registriert einen Listener für das angegebene Ereignis und akzeptiert ein Ereignis als String sowie eine Callback-Funktion.
server.on('connection', function (stream) {
  console.log('someone connected!');
});
3once(event, listener)
Registriert einen einmaligen Listener für das angegebene Ereignis, was bedeutet, dass der Listener höchstens einmal ausgelöst und unmittelbar nach dem Auslösen entfernt wird.
server.once('connection', function (stream) {
  console.log('Ah, we have our first user!');
});
4removeListener(event, listener)

Entfernt einen Listener für das angegebene Ereignis. Der Listener muss bereits für dieses Ereignis registriert worden sein.

Es akzeptiert zwei Parameter: Der erste ist der Ereignisname und der zweite der Name der Callback-Funktion.

var callback = function(stream) {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
5removeAllListeners([event])
Entfernt alle Listener für alle Ereignisse. Wenn ein Ereignis angegeben ist, entfernt es alle Listener für das angegebene Ereignis.
6setMaxListeners(n)
Standardmäßig geben EventEmitters eine Warnung aus, wenn mehr als 10 Listener hinzugefügt werden. Die Funktion setMaxListeners wird verwendet, um das Standardlimit für die Anzahl der Listener zu ändern.
7listeners(event)
Gibt ein Array von Listenern für das angegebene Ereignis zurück.
8emit(event, [arg1], [arg2], [...])
Führt jeden Listener der Reihe nach aus. Wenn das Ereignis registrierte Listener hat, gibt es true zurück; andernfalls gibt es false zurück.

Klassenmethoden

Nein.Methode & Beschreibung
1listenerCount(emitter, event)
Gibt die Anzahl der Listener für das angegebene Ereignis zurück.
events.EventEmitter.listenerCount(emitter, eventName) //已废弃,不推荐
events.emitter.listenerCount(eventName) //推荐

Einen Event-Listener registrieren:

Beispiel

const EventEmitter = require('events');
const myEmitter = new EventEmitter();

// Einen Event-Listener registrieren
myEmitter.on('sayHello', (name) => {
  console.log(`Hello, ${name}!`);
});

// Ereignis auslösen
myEmitter.emit('sayHello', 'Alice');

Ausgabe:

Hello, Alice!

Verwenden Sie once(), um ein einmaliges Ereignis zu registrieren:

myEmitter.once('init', () => {
  console.log('Initialization event occurred');
});

myEmitter.emit('init'); // 打印: Initialization event occurred
myEmitter.emit('init'); // 不会再触发

Beim Auslösen eines Ereignisses können Parameter übergeben werden, die von den Listenern verwendet werden:

Beispiel


myEmitter.on('data', (value1, value2) => {
  console.log(`Empfangene Werte: ${value1}, ${value2}`);
});

myEmitter.emit('data', 'Node.js', 'EventEmitter');
// Ausgabe: Empfangene Werte: Node.js, EventEmitter

Wenn das ausgelöste Ereignis keinen entsprechenden Listener hat, wirft EventEmitter einen Fehler:

Beispiel

myEmitter.on('error', (err) => {
  console.error('Fehlerereignis ausgelöst:', err);
});

myEmitter.emit('error', new Error('Etwas ist schiefgelaufen'));
// Ausgabe: Fehlerereignis ausgelöst: Error: Etwas ist schiefgelaufen

Ereignisse

Nein.Ereignis & Beschreibung
1newListener
  • event- Zeichenkette, der Ereignisname

  • listener- Funktion, die Ereignisbehandlungsfunktion

Dieses Ereignis wird ausgelöst, wenn ein neuer Listener hinzugefügt wird.

2removeListener
  • event- Zeichenkette, der Ereignisname

  • listener- Funktion, die Ereignisbehandlungsfunktion

Entfernt einen Listener aus dem angegebenen Listener-Array. Beachten Sie, dass diese Operation die Indizes der Listener ändert, die nach dem entfernten Listener kommen.

Beispiel

Das folgende Beispiel demonstriert die Anwendung der EventEmitter-Klasse anhand des Verbindungsereignisses.

Erstellen Sie eine Datei main.js mit folgendem Code:

Beispiel

var events = require('events');
var eventEmitter = new events.EventEmitter();

// Listener #1
var listener1 = function listener1() {
   console.log('Listener listener1 ausgeführt.');
}

// Listener #2
var listener2 = function listener2() {
  console.log('Listener listener2 ausgeführt.');
}

// Binde das connection-Ereignis, Handler-Funktion ist listener1
eventEmitter.addListener('connection', listener1);

// Binde das connection-Ereignis, Handler-Funktion ist listener2
eventEmitter.on('connection', listener2);

var eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " Listener überwachen das connection-Ereignis.");

// Behandle das connection-Ereignis
eventEmitter.emit('connection');

// Die gebundene Funktion listener1 entfernen
eventEmitter.removeListener('connection', listener1);
console.log("listener1 lauscht nicht mehr.");

// connection-Ereignis auslösen
eventEmitter.emit('connection');

eventListeners = eventEmitter.listenerCount('connection');
console.log(eventListeners + " Listener überwachen das connection-Ereignis.");

console.log("Programmausführung abgeschlossen.");

Das Ausführungsergebnis des obigen Codes ist wie folgt:

$ node main.js
2 个监听器监听连接事件。
监听器 listener1 执行。
监听器 listener2 执行。
listener1 不再受监听。
监听器 listener2 执行。
1 个监听器监听连接事件。
程序执行完毕。

error-Ereignis

EventEmitter definiert ein spezielles Ereignis, error, das die Semantik eines Fehlers trägt. Wir lösen das error-Ereignis normalerweise aus, wenn eine Ausnahme auftritt.

Wenn error ausgelöst wird, legt EventEmitter fest, dass Node.js es als Ausnahme behandelt, das Programm beendet und eine Fehlermeldung ausgibt, wenn kein entsprechender Listener vorhanden ist.

Wir setzen normalerweise Listener für Objekte, die das error-Ereignis auslösen können, um zu verhindern, dass das gesamte Programm abstürzt, nachdem ein Fehler aufgetreten ist. Zum Beispiel:

var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.emit('error'); 

Zur Laufzeit wird folgender Fehler angezeigt:

node.js:201 
throw e; // process.nextTick error, or 'error' event on first tick 
^ 
Error: Uncaught, unspecified 'error' event. 
at EventEmitter.emit (events.js:50:15) 
at Object.<anonymous> (/home/byvoid/error.js:5:9) 
at Module._compile (module.js:441:26) 
at Object..js (module.js:459:10) 
at Module.load (module.js:348:31) 
at Function._load (module.js:308:12) 
at Array.0 (module.js:479:10) 
at EventEmitter._tickCallback (node.js:192:40) 

Von EventEmitter erben

Meistens verwenden wir EventEmitter nicht direkt, sondern erben es in Objekten. Alle Kernmodule, die auf Ereignisse reagieren können, darunter fs, net und http, sind Unterklassen von EventEmitter.

Warum tun wir das? Es gibt zwei Gründe:

  • Erstens ist es semantisch angemessen, Ereignisse in einem Objekt mit einer bestimmten konkreten Funktionalität zu implementieren; Ereignisüberwachung und -auslösung sollten Methoden eines Objekts sein.

  • Zweitens ist der Objektmechanismus von JavaScript prototypbasiert und unterstützt partielle Mehrfachvererbung. Das Erben von EventEmitter stört die ursprüngliche Vererbungsbeziehung des Objekts nicht.

Die meisten Node.js-Kernmodule (wie HTTP und das Dateisystem) erben von EventEmitter. Sie können eigene Klassen erstellen, um von EventEmitter zu erben.

Beispiel

class MyEmitter extends EventEmitter {}
const customEmitter = new MyEmitter();

customEmitter.on('customEvent', () => {
  console.log('Custom event fired');
});

customEmitter.emit('customEvent');
Weitere Erweiterungen