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 warumAlso, 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.
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.
EventEmitter
MethodenEs 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 ModulenSeit 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.
So ist das bei Node EventEmitter
Klasse arbeitet. Nachfolgend finden Sie Links zur Knotendokumentation für einige der Dinge, über die wir gesprochen haben.