Verwenden des Ereignismoduls des Knotens

Als ich zum ersten Mal von Node.js gehört habe, dachte ich, es wäre nur eine JavaScript-Implementierung für den Server. Es ist jedoch viel mehr: Es verfügt über eine Reihe von integrierten Funktionen, die Sie nicht im Browser erhalten. Eine dieser Funktionen ist das Event-Modul, das über die EventEmitter Klasse. Wir werden uns das in diesem Tutorial ansehen.


EventEmitter: Was und warum

Also, was genau macht das? EventEmitter Klasse machen? Einfach ausgedrückt, können Sie auf "Ereignisse" warten und Aktionen zuweisen, die ausgeführt werden, wenn diese Ereignisse auftreten. Wenn Sie mit Front-End-JavaScript vertraut sind, kennen Sie Maus- und Tastaturereignisse, die bei bestimmten Benutzerinteraktionen auftreten. Diese sind sehr ähnlich, mit der Ausnahme, dass wir Ereignisse selbst ausgeben können, wann immer wir wollen, und nicht aufgrund von Benutzerinteraktionen erforderlich sind. Die Grundsätze EventEmitter basiert auf dem Publish / Subscribe-Modell, da wir Ereignisse abonnieren und dann veröffentlichen können. Es gibt viele Front-End-Bibliotheken, die mit Pub / Sub-Unterstützung erstellt wurden, aber Node hat es eingebaut.

Die andere wichtige Frage lautet: Warum würden Sie das Ereignismodell verwenden? In Node ist dies eine Alternative zu tief verschachtelten Rückrufen. Viele Node-Methoden werden asynchron ausgeführt. Um Code auszuführen, nachdem die Methode abgeschlossen ist, müssen Sie der Funktion eine Callback-Methode übergeben. Schließlich wird Ihr Code wie ein riesiger Trichter aussehen. Um dies zu verhindern, geben viele Knotenklassen Ereignisse aus, auf die Sie warten können. Auf diese Weise können Sie Ihren Code so organisieren, wie Sie es möchten, und keine Rückrufe verwenden.

Ein letzter Vorteil für Ereignisse: Sie sind eine sehr lose Art, Teile Ihres Codes miteinander zu verbinden. Ein Ereignis kann ausgegeben werden, aber wenn kein Code darauf wartet, ist das in Ordnung: Es wird nur unbemerkt weitergegeben. Das bedeutet, dass das Entfernen von Listenern (oder Ereignisemissionen) niemals zu JavaScript-Fehlern führt.


Verwenden EventEmitter

Wir fangen mit dem an EventEmitter Klasse für sich. Es ist ziemlich einfach zu bekommen: Wir benötigen nur das Event-Modul:

 var events = required ("Ereignisse");

Diese Veranstaltungen Das Objekt hat eine einzige Eigenschaft, nämlich die EventEmitter Klasse selbst. Lassen Sie uns ein einfaches Beispiel für den Anfang geben:

 var EventEmitter = required ("events"). EventEmitter; var ee = new EventEmitter (); ee.on ("someEvent", function () console.log ("Ereignis ist aufgetreten");); ee.emit ("someEvent");

Wir beginnen mit dem Erstellen eines neuen EventEmitter Objekt. Dieses Objekt verfügt über zwei Hauptmethoden, die wir für Ereignisse verwenden: auf und emittieren.

Wir beginnen mit auf. Diese Methode erfordert zwei Parameter: Wir beginnen mit dem Namen des Ereignisses, auf das wir warten: In diesem Fall ist das der Fall "someEvent". Aber es kann natürlich alles sein, und Sie wählen normalerweise etwas Besseres. Der zweite Parameter ist die Funktion, die beim Auftreten des Ereignisses aufgerufen wird. Das ist alles, was für die Einrichtung einer Veranstaltung erforderlich ist.

Um das Ereignis auszulösen, übergeben Sie den Ereignisnamen an die EventEmitter Instanz ist emittieren Methode. Das ist die letzte Zeile des obigen Codes. Wenn Sie diesen Code ausführen, sehen Sie, dass der Text auf der Konsole ausgedruckt wird.

Das ist die grundlegendste Verwendung eines EventEmitter. Sie können auch Daten einschließen, wenn Sie Ereignisse auslösen:

 ee.emit ("neuer Benutzer", userObj);

Dies ist nur ein Datenparameter, Sie können jedoch beliebig viele angeben. Um sie in Ihrer Event-Handler-Funktion zu verwenden, nehmen Sie sie einfach als Parameter:

 ee.on ("neuer Benutzer", Funktion (Daten) // hier Daten verwenden);

Bevor ich fortfahre, lass mich einen Teil der EventEmitter Funktionalität. Wir können für jedes Ereignis mehr als einen Zuhörer haben. Es können mehrere Ereignis-Listener zugewiesen werden (alle mit auf), und alle Funktionen werden aufgerufen, wenn das Ereignis ausgelöst wird. Standardmäßig erlaubt Node bis zu zehn Listener gleichzeitig für ein Ereignis. Wenn mehr erstellt werden, gibt der Knoten eine Warnung aus. Wir können diesen Betrag jedoch mit ändern setMaxListeners. Wenn Sie dies beispielsweise ausführen, sollte über der Ausgabe eine Warnung angezeigt werden:

 ee.on ("someEvent", function () console.log ("Ereignis 1");); ee.on ("someEvent", function () console.log ("event 2");); ee.on ("someEvent", function () console.log ("event 3");); ee.on ("someEvent", function () console.log ("event 4");); ee.on ("someEvent", function () console.log ("event 5");); ee.on ("someEvent", function () console.log ("event 6");); ee.on ("someEvent", function () console.log ("event 7");); ee.on ("someEvent", function () console.log ("event 8");); ee.on ("someEvent", function () console.log ("event 9");); ee.on ("someEvent", function () console.log ("event 10");); ee.on ("someEvent", function () console.log ("event 11");); ee.emit ("someEvent");

Um die maximale Anzahl von Zuschauern festzulegen, fügen Sie diese Zeile über den Zuhörern hinzu:

 ee.setMaxListeners (20);

Wenn Sie es jetzt ausführen, erhalten Sie keine Warnung.


Andere EventEmitter Methoden

Es gibt noch ein paar andere EventEmitter Methoden, die Sie als nützlich erachten.

Hier ist ein ordentliches: Einmal. Es ist genau wie das auf Methode, außer dass es nur einmal funktioniert. Nach dem ersten Aufruf wird der Listener entfernt.

 ee.once ("firstConnection", function () console.log ("Das werden Sie nie wieder sehen");); ee.emit ("firstConnection"); ee.emit ("firstConnection");

Wenn Sie dies ausführen, wird die Nachricht nur einmal angezeigt. Die zweite Ausgabe der Veranstaltung wird von keinem Hörer aufgegriffen (und das ist übrigens in Ordnung), weil die Einmal Listener wurde nach einmaliger Verwendung entfernt.

Apropos Hörer entfernen, wir können dies auf verschiedene Weise manuell tun. Zunächst können wir einen einzelnen Listener mit dem entfernen removeListener Methode. Es sind zwei Parameter erforderlich: der Ereignisname und die Listener-Funktion. Bisher haben wir anonyme Funktionen als Zuhörer verwendet. Wenn wir einen Listener später entfernen möchten, muss es eine Funktion mit einem Namen sein, auf den wir verweisen können. Wir können das nutzen removeListener Methode, um die Auswirkungen der Einmal Methode:

 function onlyOnce () console.log ("Sie werden das nie wieder sehen"); ee.removeListener ("firstConnection", nurOnce);  ee.on ("firstConnection", nurOnce) ee.emit ("firstConnection"); ee.emit ("firstConnection");

Wenn Sie dies ausführen, werden Sie feststellen, dass es den gleichen Effekt hat wie Einmal.

Wenn Sie alle Listener entfernen möchten, die an ein bestimmtes Ereignis gebunden sind, können Sie verwenden removeAllListeners; Übergeben Sie einfach den Namen der Veranstaltung:

 ee.removeAllListeners ("firstConnection");

Um alle Listener für alle Ereignisse zu entfernen, rufen Sie die Funktion ohne Parameter auf.

ee.removeAllListeners ();

Es gibt eine letzte Methode: Hörer. Diese Methode nimmt einen Ereignisnamen als Parameter und gibt ein Array aller Funktionen zurück, die auf dieses Ereignis warten. Hier ist ein Beispiel dafür, basierend auf unserem nur einmal Beispiel:

 function onlyOnce () console.log (ee.listeners ("firstConnection")); ee.removeListener ("firstConnection", nurOnce); console.log (ee.listeners ("firstConnection"));  ee.on ("firstConnection", nurOnce) ee.emit ("firstConnection"); ee.emit ("firstConnection");

Wir werden diesen Abschnitt mit einem bisschen Meta-Ness beenden. Unsere EventEmitter Die Instanz selbst löst eigentlich zwei eigene Ereignisse aus, auf die wir hören können: Eines, wenn wir neue Zuhörer erstellen, und eines, wenn wir sie entfernen. Siehe hier:

 ee.on ("newListener", Funktion (evtName, fn) console.log ("New Listener:" + evtName);); ee.on ("removeListener"), Funktion (evtName) console.log ("Entfernter Listener:" + evtName);); function foo ()  ee.on ("save-user", foo); ee.removeListener ("save-user", foo);

Wenn Sie dies ausführen, sehen Sie unsere Listener für neue und entfernte Listener, und wir erhalten die erwarteten Nachrichten.

Nun, da wir alle Methoden gesehen haben, die ein EventEmitter Beispiel hat, sehen wir, wie es in Verbindung mit anderen Modulen funktioniert.

EventEmitter Innerhalb von Modulen

Seit der EventEmitter class ist nur ein reguläres JavaScript, es ist absolut sinnvoll, dass es in anderen Modulen verwendet werden kann. In Ihren eigenen JavaScript-Modulen können Sie erstellen EventEmitter Instanzen, und verwenden Sie sie, um interne Ereignisse zu behandeln. Das ist doch ganz einfach. Interessanter wäre es, ein Modul zu erstellen, das von erbt EventEmitter, So können wir seine Funktionalität als Teil der öffentlichen API verwenden.

Tatsächlich gibt es eingebaute Knotenmodule, die genau dies tun. Zum Beispiel kennen Sie vielleicht die http Modul; Mit diesem Modul erstellen Sie einen Webserver. Dieses grundlegende Beispiel zeigt, wie das auf Methode der EventEmitter Klasse ist Teil der http.Server Klasse:

 var http = erfordern ("http"); var server = http.createServer (); server.on ("request", function (req, res) res.end ("das ist die Antwort");); Server.listen (3000);

Wenn Sie dieses Snippet ausführen, wartet der Prozess auf eine Anfrage. Sie können zu gehen http: // localhost: 3000 und du bekommst die Antwort. Wenn die Serverinstanz die Anfrage von Ihrem Browser erhält, gibt sie eine "anfordern" Ereignis, ein Ereignis, das unser Zuhörer empfängt und handeln kann.

Wie können wir also eine Klasse erstellen, die von erben wird? EventEmitter? Es ist eigentlich nicht so schwierig. Wir schaffen ein einfaches Benutzerliste Klasse, die Benutzerobjekte behandelt. Also in einer userlist.js Datei, wir fangen damit an:

 var util = erfordern ("util"); var EventEmitter = required ("events"). EventEmitter;

Wir brauchen die util Modul, um bei der Vererbung zu helfen. Als Nächstes benötigen wir eine Datenbank: Anstelle einer tatsächlichen Datenbank verwenden wir nur ein Objekt:

 var id = 1; var database = Benutzer: [id: id ++, Name: "Joe Smith", Beruf: "Entwickler", id: id ++, Name: "Jane Doe", Beruf: "Datenanalyst", id: id ++ , Name: "John Henry", Beruf: "Designer"];

Jetzt können wir unser Modul tatsächlich erstellen. Wenn Sie mit Knotenmodulen nicht vertraut sind, funktionieren sie wie folgt: Jedes in diese Datei geschriebene JavaScript kann standardmäßig nur innerhalb der Datei gelesen werden. Wenn wir es in die öffentliche API des Moduls aufnehmen möchten, machen wir es zu einer Eigenschaft von modul.exporte, oder ordnen Sie ein ganz neues Objekt oder eine Funktion zu modul.exporte. Lass uns das machen:

 function UserList () EventEmitter.call (this); 

Dies ist die Konstruktorfunktion, aber es ist nicht Ihre übliche JavaScript-Konstruktorfunktion. Was wir hier machen, ist das Anruf Methode auf der EventEmitter Konstruktor, um diese Methode auf dem neuen auszuführen Benutzerliste Objekt (was ist diese). Wenn wir eine andere Initialisierung für unser Objekt vornehmen müssen, können wir dies innerhalb dieser Funktion tun, aber das ist alles, was wir jetzt tun werden.

Das Erben des Konstruktors reicht jedoch nicht aus. Wir müssen auch den Prototyp erben. Dies ist, wo die util Modul kommt rein.

 util.inherits (UserList, EventEmitter);

Dadurch wird alles hinzugefügt, was läuft EventEmitter.prototype zu UserList.prototype; jetzt unser Benutzerliste Instanzen haben alle Methoden eines EventEmitter Beispiel. Aber wir wollen natürlich noch etwas hinzufügen. Wir werden ein hinzufügen sparen Methode, um neue Benutzer hinzufügen zu können.

 UserList.prototype.save = Funktion (obj) obj.id = id ++; database.users.push (obj); this.emit ("gespeicherter Benutzer", obj); ;

Diese Methode benötigt ein zu speicherndes Objekt "Datenbank": fügt ein hinzu Ich würde und schiebt es in das Benutzerarray. Dann strahlt es das aus "gespeicherter Benutzer" Ereignis und übergibt das Objekt als Daten. Wenn es sich um eine echte Datenbank handelt, wäre das Speichern wahrscheinlich eine asynchrone Aufgabe. Wenn Sie also mit dem gespeicherten Datensatz arbeiten möchten, müssen Sie einen Rückruf akzeptieren. Die Alternative dazu ist, wie wir eine Veranstaltung auszustrahlen. Wenn wir jetzt etwas mit dem gespeicherten Datensatz machen wollen, können wir einfach auf das Ereignis hören. Wir machen das gleich. Lass uns einfach das schließen Benutzerliste

 UserList.prototype.all = function () return database.users; ; module.exports = Benutzerliste;

Ich habe eine weitere Methode hinzugefügt: eine einfache Methode, die alle Benutzer zurückgibt. Dann ordnen wir zu Benutzerliste zu modul.exporte.

Nun sehen wir das in Gebrauch; sagen wir in einer anderen Datei test.js. Fügen Sie folgendes hinzu:

 var UserList = required ("./ userlist"); var users = neue Benutzerliste (); users.on ("gespeicherter Benutzer", Funktion (Benutzer) console.log ("gespeichert:" + user.name + "(" + user.id + ")");); users.save (Name: "Jane Doe", Beruf: "Manager"); users.save (Name: "John Jacob", Beruf: "Entwickler");

Nachdem wir unser neues Modul angefordert und eine Instanz davon erstellt haben, lauschen wir dem "gespeicherter Benutzer" Veranstaltung. Dann können wir einige Benutzer speichern. Wenn Sie dies ausführen, werden Sie sehen, dass wir zwei Meldungen erhalten, die Namen und IDs der gespeicherten Datensätze ausdrucken.

 gerettet: Jane Doe (4) gerettet: John Jacob (5)

Das könnte natürlich auch andersherum funktionieren: Wir könnten die verwenden auf Methode aus unserer Klasse und der emittieren Methode draußen oder beides innen oder außen. Dies ist jedoch ein gutes Beispiel dafür, wie dies getan werden könnte.


Fazit

So ist das bei Node EventEmitter Klasse arbeitet. Nachfolgend finden Sie Links zur Knotendokumentation für einige der Dinge, über die wir gesprochen haben.

  • Knotenereignismodul
  • Knoten-Util-Modul
  • Node HTTP Agent Source - Hier wird das von uns verwendete Vererbungsmuster angezeigt.