Gebeurtenisafhandeling in Node.js

In Node.js veel van de objecten in de omgeving zenden gebeurtenissen uit, bijvoorbeeld een TCP-server zendt een gebeurtenis uit van het type aansluiten elke keer dat een nieuwe client verbinding maakt of een stroom bestanden informatie uitzendt elke keer dat een stukje informatie wordt gelezen.

Dit in Node.js is wat gebeurteniszenders worden genoemd, die ontwikkelaars de mogelijkheid bieden om gebeurtenissen te abonneren, waarbij het een functie onderschrijft Bel terug die wordt aangeroepen elke keer dat een gebeurtenis in de gebeurteniszender plaatsvindt. We kunnen zelfs onze eigen gebeurteniszenders maken dankzij de pseudo-klasse EventEmitter.

Om echter met de gebeurteniszenders binnen te komen, moeten we eerst enkele concepten duidelijk hebben, zoals sommige patronen van deze functies, de soorten gebeurtenissen en zelfs de luisteraars.

VereistenOm de oefeningen die in deze tutorial worden voorgesteld uit te voeren, moeten we een functionele installatie hebben van: Node.js in ons systeem kunnen we deze tutorial bekijken voordat we ons er verder in gaan verdiepen. Het is ook belangrijk om toegang te hebben tot een rich text-editor om de voorbeelden te coderen, we kunnen alles gebruiken waar we ons prettig bij voelen, maar vanwege het gebruiksgemak raden we aan Sublieme tekst o NotePad ++ die ook plug-ins hebben voor de syntaxis JavaScript Y HTML.

Patroon voor terugbellen


Asynchrone programmering gebruikt de terugkeer van waarden in de functies niet om aan te geven dat die functie net is voltooid, maar roept de beroemde callback op nadat de bewerking is voltooid, zodat ons programma kan doorgaan, waar JavaScript Ik leid tot dit type programmering, laten we een voorbeeld bekijken in Geef niet die een bestand leest en de inhoud in het geheugen laadt:
 var fs = vereisen ('fs'); fs.readFile ('file.txt', function (err, fileContent) {if (err) {throw err;} console.log ('File content:', fileContent.toString ());});
Wat we hier doen, is dat we een anonieme functie verzenden als het tweede argument van de functie fs.readFile, en hoe kunnen we zien dat het eerste argument van de callback-functie een error-object is, dat een instantie van de Error-klasse zal hebben als er een fout optreedt.

Patroon voor de gebeurteniszender


De vorige stijl werkt perfect wanneer we willen melden dat een functie die we uitvoeren zijn werk voltooit, maar in het geval dat er meerdere gebeurtenissen plaatsvinden tijdens deze uitvoering of vele malen, zal deze stijl niet werken zoals we willen. Als we bijvoorbeeld een melding willen krijgen telkens wanneer de informatie beschikbaar is in de socket, een functie van het type Bel terug standaard zal ons niet veel helpen, maar dit is waar de gebeurteniszender ons kan helpen.

De gebeurteniszender is niets meer dan een object dat, zoals de naam aangeeft, een gebeurtenis uitzendt, waarbij a luisteraar het maakt deel uit van de code die aan deze zender bindt en luistert naar bepaalde soorten gebeurtenissen, zoals:

 var req = http.request (opties, functie (respons) {response.on ("data", functie (data) {console.log ("Sommige responsgegevens", gegevens);}); response.on (" einde " , functie () {console.log ("voltooid antwoord ");});}); verzoek.einde ();
Dit is een louter verklarende code, waar we enkele stappen kunnen zien om een ​​verzoek in te dienen HTTP naar een externe server, maar het stelt ons in staat om te zien hoe het responsobject een gebeurteniszender is, die niet alleen kan uitzenden: gegevens Y einde maar ook andere soorten evenementen.

Soorten evenementen


Volgens het vorige voorbeeld konden we zien dat de uitgezonden gebeurtenissen altijd een type hebben, dat wordt weergegeven door een tekenreeks, in dit geval "gegevens"J"einde”, Dit zijn willekeurige reeksen die zijn aangewezen door de uitgever van het evenement.

De gebeurteniszender is een generieke interface die elk type gebeurtenis bedient, maar er is een speciaal geval in de implementatie van Geef niet en het is het evenement fout, waarbij elke gebeurtenis in de omgeving een gebeurtenis van dit type uitzendt elke keer dat er een fout optreedt en als de ontwikkelaar ervoor kiest om niet naar dit type gebeurtenis te luisteren en er een fout optreedt, zal de gebeurteniszender dit opmerken en in dit geval een uitzondering maken . Laten we in de volgende code kijken hoe we dit gedrag kunnen simuleren:

 var em = nieuw (vereiste ('evenementen'). EventEmitter) (); em.emit ('gebeurtenis1'); em.emit ('fout', nieuwe fout ('Mijn fout'));
Als we het door de console laten lopen, kunnen we zien hoe: Geef niet vertelt ons dat we de fout niet afhandelen, waardoor een niet-afgevangen uitzondering wordt gegenereerd:

Omdat we hebben gezien hoe gebeurtenissen zich in het algemeen gedragen, laten we eens kijken hoe we de gebeurteniszender-API gebruiken.

De gebeurteniszender-API gebruiken


Elk object dat het gebeurtenisemitterpatroon implementeert, implementeert een reeks gebeurtenissen, zoals we hieronder kunnen zien:

.addListener - .onMet deze methode kunnen we een luisteraar toevoegen aan een gebeurtenistype.
.elfMet deze methode kunnen we een luisteraar binden aan een gebeurtenistype, aangezien het minstens één keer zal worden aangeroepen.
.removeEventListenerMet deze methode kunnen we een luisteraar van een bepaalde gebeurtenis verwijderen.
.removeAllEventListenersTen slotte helpt deze methode ons om alle luisteraars voor een bepaald type gebeurtenis te verwijderen.
Nu we al hebben gezien wat de functie van elk van deze is, laten we eens kijken hoe we ze in onze programma's gebruiken.

.addListener () of .on () gebruiken bij terugbellen


Door een gebeurtenistype en een functie op te geven Bel terug, kunnen we de actie vastleggen die moet worden ondernomen wanneer een specifieke gebeurtenis plaatsvindt. Als we bijvoorbeeld willen worden geïnformeerd dat een deel van de gegevens beschikbaar is en een gebeurtenis van het type gegevens willen uitzenden, kunnen we het volgende doen:
 functie ReceiveData (data) {console.log ("De gegevens zijn verkregen:% j", data); } readFlow.addListener ("gegevens", ontvangData);
We kunnen de methode ook gebruiken: .Aan () wat slechts een snelkoppeling is, laten we het equivalent van de vorige code eens bekijken:
 functie ReceiveData (data) {console.log ("De gegevens zijn verkregen:% j", data); } readFlow.on ("gegevens", gegevens ontvangen);
We kunnen zelfs meerdere luisteraars voor onze evenementen toevoegen om naar hetzelfde type evenement op dezelfde zender te luisteren, bijvoorbeeld:

In dit voorbeeld worden twee functies aan de gebeurtenis van het gegevenstype gekoppeld, en wanneer de gegevensgebeurtenis eenmaal is uitgezonden, worden beide tekenreeksen afgedrukt. Het is belangrijk op te merken dat de uitgever van het evenement verantwoordelijk is voor het bellen van alle luisteraars geregistreerd voor een gebeurtenistype, en het zal ze aanroepen in de volgorde waarin ze zijn geregistreerd, wat het volgende betekent:

  • Een luisteraar kan niet direct worden gebeld nadat de gebeurtenis is uitgezonden, het is mogelijk dat eerder andere luisteraars worden gebeld.
  • Het niet opvangen van uitzonderingen is ongezond gedrag voor onze code, dus als een van deze listeners een fout genereert en niet wordt opgevangen, is het mogelijk dat sommige listeners niet worden aangeroepen, waar we dit in het volgende voorbeeld kunnen illustreren:

Waar in dit voorbeeld de tweede luisteraar niet wordt aangeroepen omdat de eerste een fout heeft veroorzaakt.

.removeListener () gebruiken


Als we op enig moment niet langer op de hoogte willen worden gehouden van wijzigingen aan een specifieke gebeurtenis of object, kunnen we de opname stoppen door het type gebeurtenis en de callback-functie als volgt op te geven:

.once () gebruiken


In het geval dat onze applicatie luistert naar een evenement dat minstens één keer zal plaatsvinden of als we slechts geïnteresseerd zijn om het maar één keer te laten gebeuren, kunnen we gebruiken .elf(), die de luisteraar toevoegt en verwijdert zodra de eerste gebeurtenis plaatsvindt:

.removeAllListeners gebruiken ()


Ten slotte kunnen we als volgt alle luisteraars voor een bepaald gebeurtenistype van een gebeurteniszender verwijderen:
 uitgever.removeAllListeners (type);

De gebeurteniszender maken


De gebeurteniszender biedt ons een generieke manier om interfaces te maken, omdat we gebeurtenissen binden in plaats van functies, waardoor ons programma flexibeler wordt, zelfs als we het patroon van willen gebruiken Node.js In onze hele applicatie kunnen we een pseudo-klasse maken en erven van EventEmitter als volgt:
 util = vereisen ('util'); var EventEmitter = vereisen ('gebeurtenissen'). EventEmitter; var MyClass = function () {} util.inherits (MyClass, EventEmitter);
Op deze manier worden de methoden van EventEmitter Ze zullen beschikbaar zijn voor onze instantie en we kunnen ze zonder problemen en op deze manier gebruiken Mijn klas kan gebeurtenissen uitzenden:
 MyClass.prototype.someMethod = function () {this.emit ("aangepaste gebeurtenis", "argument 1", "argument 2"); };
Hier wanneer? een methode wordt genoemd in het geval van Mijn klas, het voorbeeld zendt een gebeurtenis uit met de naam aangepaste gebeurtenis, waar het op zijn beurt twee verschillende gegevens uitzendt, argument 1 en argument 2, die naar de gebeurtenislisteners worden verzonden. Eindelijk in de gevallen van Mijn klas aan de clientzijde kun je luisteren naar de aangepaste gebeurtenis als volgt:
 var MijnKlasse = nieuwe MijnKlasse (); MyClass.on ('aangepaste gebeurtenis', functie (str1, str2) {console.log ('Aangepaste gebeurtenis geluisterd met argumenten str1% s en str2% s!', Str1, str2);});
Zoals we kunnen zien, helpt het gebruik van gebeurtenissen samen met de gebeurteniszender ons om met onze applicatie te communiceren en zo hebben we deze tutorial beëindigd, waar we verder konden gaan dan asynchrone programmering en het toepassen van praktijken die ons helpen een standaard en optimale patroon voor onze toepassingen.

wave wave wave wave wave