mitmario.dev

EventEmitter

Node.js Sandbox 3 Min Lesezeit 3 BeispieleLektion 1 von 7

Das nächste Muster kennst du schon, du hast es nur woanders gesehen. Im Browser hast du addEventListener benutzt: Irgendwo passiert etwas, und dein Code reagiert darauf, ohne dass die auslösende Stelle wissen muss, wer zuhört.

In Node heißt das EventEmitter, und der Unterschied ist nur, dass es nicht an einem DOM-Knoten hängt, sondern an einem beliebigen Objekt. Die halbe Standardbibliothek baut darauf auf: Server, Sockets, Streams, Kindprozesse. Wer das Muster kennt, liest fremden Node-Code plötzlich flüssig.

Vier Methoden, mehr braucht es nicht

on meldet einen Zuhörer an. emit löst ein Ereignis aus. once meldet einen Zuhörer an, der nach dem ersten Mal wieder verschwindet. off meldet einen Zuhörer wieder ab.

Zuhören und melden
import { EventEmitter } from "node:events";

const kueche = new EventEmitter();

kueche.on("bestellung", (tisch, gericht) => {
  console.log(`Tisch ${tisch} bekommt ${gericht}`);
});

kueche.emit("bestellung", 4, "Suppe");
kueche.emit("bestellung", 7, "Salat");

Der Ereignisname ist eine Zeichenkette, die du frei wählst. Alles, was du hinter dem Namen an emit übergibst, kommt bei den Zuhörern als Argumente an, in derselben Reihenfolge. Es gibt kein festes Format und keine Anmeldung von Ereignisnamen. Ein Tippfehler im Namen ist deshalb kein Fehler, sondern einfach ein Ereignis, auf das niemand hört.

once, wenn es nur beim ersten Mal zählt

once hört nur einmal zu
import { EventEmitter } from "node:events";

const melder = new EventEmitter();

melder.on("tick", (nummer) => console.log(`on: ${nummer}`));
melder.once("tick", (nummer) => console.log(`once: ${nummer}`));

melder.emit("tick", 1);
melder.emit("tick", 2);
melder.emit("tick", 3);

once ist kein Sonderfall von on, sondern der normale Weg für alles, was einmalig ist: „Verbindung steht”, „Datei ist fertig gelesen”, „Server hört jetzt zu”. Der Zuhörer entfernt sich selbst, und du musst nicht daran denken, ihn wieder abzumelden.

Das ist mehr als Bequemlichkeit. Zuhörer, die niemand abmeldet, sind eine der klassischen Ursachen für ein Programm, dessen Speicherverbrauch langsam steigt. Node warnt dich sogar, wenn an einem Ereignis mehr als zehn Zuhörer hängen, und genau darum geht es bei dieser Warnung.

Der Punkt, der die meisten überrascht

emit ruft sofort auf
import { EventEmitter } from "node:events";

const melder = new EventEmitter();

melder.on("fertig", () => console.log("der Zuhoerer laeuft"));

console.log("vor emit");
melder.emit("fertig");
console.log("nach emit");

emit ruft die Zuhörer synchron auf. Direkt, nacheinander, mitten in der Zeile, in der emit steht. Nichts daran ist „später” oder „im Hintergrund”.

Das hat zwei Folgen, die man kennen sollte. Erstens: Wenn ein Zuhörer lange rechnet, hält er die Stelle auf, die emit aufgerufen hat. Ein Ereignis ist kein Weg, Arbeit loszuwerden. Zweitens: Ein Zuhörer, der du erst nach dem emit anmeldest, verpasst es. Ereignisse werden nicht aufgehoben. Deshalb hängt man die Zuhörer immer an, bevor man das Objekt losschickt.

Wenn ein Zuhörer eine async-Funktion ist, wartet emit übrigens nicht auf sie. Es ruft sie auf, bekommt ein Promise zurück und wirft es weg. Wer auf ein Ergebnis warten will, ist bei Ereignissen falsch, und darum geht es gleich in Lektion 7.2.

Wozu das gut ist

Der eigentliche Gewinn steckt in dem, was nicht im Code steht. Die Küche im ersten Beispiel weiß nicht, wer ihre Bestellungen entgegennimmt. Sie meldet nur, dass eine da ist.

Damit kannst du später einen zweiten Zuhörer dazuhängen, der die Bestellung mitschreibt, und danach einen dritten, der eine Statistik führt. An der Küche ändert sich dabei nichts. Genau dafür ist das Muster gedacht: eine Stelle meldet, dass etwas passiert ist, ohne wissen zu müssen, wen das interessiert.

Zum Mitnehmen

on zum Zuhören, emit zum Auslösen, once für genau ein Mal. Und emit ruft die Zuhörer synchron auf, nicht später.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.

Was in dieser Lektion steckt

  • Artikel mit 3 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.