Ereignisbehandlung in Node.js

In Node.js Viele der in der Umgebung vorhandenen Objekte senden Ereignisse aus, zum Beispiel sendet ein TCP-Server ein Ereignis vom Typ . aus verbinden jedes Mal, wenn sich ein neuer Client verbindet oder ein Dateistrom Informationen ausgibt, jedes Mal, wenn eine Information gelesen wird.

Das in Node.js sind sogenannte Event-Emitter, die Entwicklern die Möglichkeit geben, Events zu abonnieren, wenn sie eine Funktion abonnieren Ruf zurück die jedes Mal aufgerufen wird, wenn ein Ereignis im Ereignisemitter auftritt. Dank der Pseudoklasse können wir sogar eigene Event-Emitter erstellen EventEmitter.

Um jedoch mit den Ereignis-Emittern zu beginnen, müssen wir uns zunächst über einige Konzepte im Klaren sein, wie etwa einige Muster dieser Funktionen, die Arten von Ereignissen und sogar die Listener.

AnforderungenUm die in diesem Tutorial vorgeschlagenen Übungen ausführen zu können, benötigen wir eine funktionsfähige Installation von Node.js In unserem System können wir uns dieses Tutorial ansehen, bevor wir uns weiter damit befassen. Es ist auch wichtig, Zugriff auf einen Rich-Text-Editor zu haben, um die Beispiele zu codieren. Wir können alles verwenden, womit wir uns wohl fühlen, aber wegen seiner Benutzerfreundlichkeit empfehlen wir Erhabener Text o NotePad ++, die auch Plugins für die Syntax haben JavaScript Ja HTML.

Muster für Rückrufe


Die asynchrone Programmierung verwendet nicht die Rückgabe von Werten in den Funktionen, um anzuzeigen, dass diese Funktion gerade beendet wurde, sondern ruft nach Abschluss der Operation den berühmten Callback auf, damit unser Programm fortfahren kann, wo JavaScript Ich führe zu dieser Art der Programmierung, sehen wir ein Beispiel in Gib nicht die eine Datei liest und ihren Inhalt in den Speicher lädt:
 var fs = erfordern ('fs'); fs.readFile ('file.txt', function (err, fileContent) {if (err) {throw err;} console.log ('Dateiinhalt:', fileContent.toString ());});
Was wir hier tun, ist, dass wir eine anonyme Funktion als zweites Argument der Funktion senden fs.readFile, und wie können wir sehen, dass das erste Argument der Callback-Funktion ein Fehlerobjekt ist, das eine Instanz der Error-Klasse hat, wenn ein Fehler auftritt.

Muster für den Ereignissender


Der vorherige Stil funktioniert perfekt, wenn wir benachrichtigen möchten, dass eine Funktion, die wir ausführen, ihre Arbeit beendet, aber für den Fall, dass während dieser Ausführung mehrere Ereignisse oder mehrmals stattfinden, wird dieser Stil nicht wie gewünscht funktionieren. Wenn wir beispielsweise jedes Mal benachrichtigt werden möchten, wenn die Informationen im Socket verfügbar sind, ist eine Funktion des Typs Ruf zurück standard wird uns nicht viel helfen, aber hier kann uns der Event-Emitter helfen.

Der Ereignissender ist nichts anderes als ein Objekt, das, wie der Name schon sagt, ein Ereignis aussendet, wobei a Hörer Es ist Teil des Codes, der an diesen Emitter bindet und auf bestimmte Arten von Ereignissen lauscht, wie zum Beispiel:

 var req = http.request (Optionen, Funktion (Antwort) {Antwort.on ("Daten", Funktion (Daten) {console.log ("Einige Antwortdaten", Daten);}); response.on ("Ende" , Funktion () {console.log ("abgeschlossene Antwort");});}); erf.ende ();
Dies ist ein rein erklärender Code, in dem wir einige der Schritte sehen können, um eine Anfrage zu stellen HTTP zu einem entfernten Server, aber es ermöglicht uns zu sehen, wie das Antwortobjekt ein Ereignissender ist, der nicht nur ausgeben kann Daten Ja Ende aber auch andere Arten von Veranstaltungen.

Arten von Veranstaltungen


Nach dem vorherigen Beispiel konnten wir sehen, dass die ausgegebenen Ereignisse immer einen Typ haben, der in diesem Fall durch eine Zeichenfolge dargestellt wird "Daten"Y"Ende”, Dabei handelt es sich um willkürliche Zeichenfolgen, die vom Ereignisaussteller bestimmt werden.

Der Event-Emitter ist eine generische Schnittstelle, die jede Art von Event bedient, aber es gibt einen Sonderfall bei der Implementierung von Gib nicht und es ist die veranstaltung Error, wobei jedes Ereignis in der Umgebung jedes Mal ein Ereignis dieses Typs ausgibt, wenn ein Fehler auftritt . Sehen wir uns im folgenden Code an, wie wir dieses Verhalten simulieren können:

 var em = new (require ('events'). EventEmitter) (); em.emit ('Ereignis1'); em.emit ('Fehler', neuer Fehler ('Mein Fehler'));
Wenn wir es über die Konsole ausführen, können wir sehen, wie Gib nicht teilt uns mit, dass wir den Fehler nicht behandeln, wodurch eine nicht abgefangene Ausnahme generiert wird:

Da wir gesehen haben, wie sich Ereignisse im Allgemeinen verhalten, sehen wir uns an, wie wir die Ereignisemitter-API verwenden.

Verwenden der Ereignisemitter-API


Jedes Objekt, das das Ereignisemittermuster implementiert, implementiert eine Reihe von Ereignissen, wie wir unten sehen können:

.addListener - .onMit dieser Methode können wir einem Ereignistyp einen Listener hinzufügen.
.elfMit dieser Methode können wir einen Listener an einen Ereignistyp binden, vorausgesetzt, dass er mindestens einmal aufgerufen wird.
.removeEventListenerDiese Methode ermöglicht es uns, einen Listener aus einem bestimmten Ereignis zu entfernen.
.removeAllEventListenersSchließlich hilft uns diese Methode, alle Listener für einen bestimmten Ereignistyp zu entfernen.
Nachdem wir bereits gesehen haben, welche Funktion diese haben, wollen wir sehen, wie wir sie in unseren Programmen verwenden.

Verwenden von .addListener () oder .on () in Rückrufen


Durch Angabe eines Ereignistyps und einer Funktion Ruf zurück, können wir die Aktion aufzeichnen, die ausgeführt werden soll, wenn ein bestimmtes Ereignis eintritt. Wenn wir beispielsweise darüber informiert werden möchten, dass ein Teil der Daten verfügbar ist und ein Ereignis vom Typ Daten ausgeben möchten, können wir Folgendes tun:
 Funktion ReceiveData (Daten) {console.log ("Die Daten wurden erhalten: % j", Daten); } readFlow.addListener ("data", receiveData);
Wir können auch die Methode verwenden .an () Was nur eine Abkürzung ist, sehen wir uns das Äquivalent des vorherigen Codes an:
 Funktion ReceiveData (Daten) {console.log ("Die Daten wurden erhalten: % j", Daten); } readFlow.on ("data", receiveData);
Wir können sogar mehrere Listener für unsere Ereignisse hinzufügen, um denselben Ereignistyp auf demselben Sender zu hören, zum Beispiel:

In diesem Beispiel werden zwei Funktionen an das Datentypereignis gebunden, und sobald das Datenereignis ausgegeben wird, werden beide Zeichenfolgen gedruckt. Es ist wichtig zu beachten, dass der Ereignisaussteller dafür verantwortlich ist, alle anzurufen Zuhörer für einen Ereignistyp registriert und ruft sie in der Reihenfolge auf, in der sie registriert wurden, was Folgendes bedeutet:

  • Ein Listener kann nicht sofort nach der Ausgabe des Ereignisses aufgerufen werden, es ist möglich, dass andere Listener zuvor aufgerufen werden.
  • Ausnahmen nicht abzufangen ist ein ungesundes Verhalten für unseren Code. Wenn also einer dieser Listener einen Fehler auslöst und nicht abgefangen wird, ist es möglich, dass einige Listener nicht aufgerufen werden, wo wir dies im folgenden Beispiel veranschaulichen können:

Wobei in diesem Beispiel der zweite Listener nicht aufgerufen wird, da der erste einen Fehler verursacht hat.

Verwenden von .removeListener()


Wenn wir zu einem bestimmten Zeitpunkt nicht mehr über Änderungen an einem bestimmten Ereignis oder Objekt informiert werden möchten, können wir die Aufzeichnung durch Angabe der Art des Ereignisses und der Callback-Funktion wie folgt beenden:

Einmal verwenden ()


Für den Fall, dass unsere Anwendung auf ein Ereignis wartet, das mindestens einmal stattfinden wird, oder wenn wir nur daran interessiert sind, dass es nur einmal stattfindet, können wir verwenden .elf(), wodurch der Listener hinzugefügt und entfernt wird, sobald das erste Ereignis auftritt:

Verwenden von .removeAllListeners()


Schließlich können wir alle Listener für einen bestimmten Ereignistyp wie folgt aus einem Ereignisemitter entfernen:
 Issuer.removeAllListeners (Typ);

Erstellen des Ereignissenders


Der Event-Emitter bietet uns eine generische Möglichkeit, Schnittstellen zu erstellen, da wir Ereignisse anstelle von Funktionen binden, was unser Programm flexibler macht, auch wenn wir das Muster von verwenden möchten Node.js Während unserer gesamten Anwendung können wir eine Pseudoklasse erstellen und davon erben EventEmitter wie folgt:
 util = erfordern ('util'); var EventEmitter = require ('Ereignisse').EventEmitter; var MyClass = function () {} util.inherits (MyClass, EventEmitter);
Auf diese Weise sind die Methoden von EventEmitter Sie werden für unsere Instanz verfügbar sein und wir können sie problemlos und auf diese Weise verwenden Meine Klasse kann Ereignisse ausgeben:
 MyClass.prototype.someMethod = function () {this.emit ("benutzerdefiniertes Ereignis", "Argument 1", "Argument 2"); };
Hier wenn eine Methode heißt im Fall von Meine Klasse, gibt das Beispiel ein Ereignis namens . aus benutzerdefiniertes Ereignis, wobei es wiederum zwei verschiedene Daten ausgibt, Argument 1 und Argument 2, die an die Ereignis-Listener gesendet werden. Schließlich in den Fällen von Meine Klasse auf der Client-Seite können Sie sich das anhören benutzerdefiniertes Ereignis wie folgt:
 var MyClass = neue MyClass (); MyClass.on ('benutzerdefiniertes Ereignis', Funktion (str1, str2) {console.log ('Benutzerdefiniertes Ereignis mit den Argumenten str1% s und str2% s abgehört!', Str1, str2);});
Wie wir sehen, hilft uns die Verwendung von Events zusammen mit dem Event-Emitter bei der Kommunikation mit unserer Anwendung und so haben wir dieses Tutorial beendet, in dem wir über die asynchrone Programmierung und die Anwendung von Praktiken hinausgehen konnten, die uns helfen, einen Standard und ein Optimum beizubehalten Muster für unsere Anwendungen.

wave wave wave wave wave