Folosind modulul de evenimente al nodului

Când am auzit prima dată despre Node.js, am crezut că a fost doar o implementare JavaScript pentru server. Dar este de fapt mult mai mult: vine cu o serie de funcții încorporate pe care nu le primiți în browser. Unul dintre acești biți de funcționalitate este modulul Eveniment, care are EventEmitter clasă. Ne vom uita la asta în acest tutorial.


EventEmitter: Ce și de ce

Deci, ce anume face EventEmitter clasa face? Pune simplu, vă permite să ascultați pentru "evenimente" și să alocați acțiuni pentru a rula atunci când acele evenimente apar. Dacă sunteți familiarizați cu JavaScript frontală, veți ști despre evenimentele mouse-ului și ale tastaturii care apar în anumite interacțiuni ale utilizatorilor. Acestea sunt foarte asemănătoare, cu excepția faptului că putem să emităm evenimente pe cont propriu, atunci când dorim, și nu pe baza interacțiunii utilizatorilor. Principiile EventEmitter se bazează pe modelul de publicare / abonare, pentru că ne putem abona la evenimente și le putem publica. Există multe biblioteci front-end construite cu suport pub / sub, dar nodul o construiește.

Cealaltă întrebare importantă este următoarea: de ce ați folosi modelul evenimentului? În Nod, este o alternativă la apelurile aduse în profunzime. O mulțime de metode Node sunt executate asincron, ceea ce înseamnă că pentru a rula cod după terminarea metodei, trebuie să treci o metodă de apel invers la funcție. În cele din urmă, codul dvs. va arăta ca o pâlnie gigantică. Pentru a preveni acest lucru, multe clase de noduri emit evenimente pe care le puteți asculta. Acest lucru vă permite să vă organizați codul așa cum doriți și să nu utilizați apeluri de apel.

Un ultim beneficiu pentru evenimente: acestea reprezintă o modalitate foarte slabă de cuplare a unor părți ale codului împreună. Un eveniment poate fi emis, dar dacă nici un cod nu ascultă, este în regulă: tocmai a trecut neobservat. Aceasta înseamnă că eliminarea ascultătorilor (sau a emisiilor de evenimente) nu duce niciodată la erori de JavaScript.


Utilizarea EventEmitter

Vom începe cu EventEmitter clasa pe cont propriu. Este destul de simplu să ajungeți la: solicităm doar modulul de evenimente:

 var evenimente = cer ("evenimente");

Acest evenimente obiect are o singură proprietate, care este EventEmitter clasa însăși. Deci, să facem un exemplu simplu pentru începători:

 var EventEmitter = necesită ("evenimente") EventEmitter; var ee = noul EventEmitter (); ee.on ("someEvent", funcția () console.log ("evenimentul a apărut");); ee.emit ( "someEvent");

Începem prin a crea un nou EventEmitter obiect. Acest obiect are două metode principale pe care le folosim pentru evenimente: pe și emite.

Începem cu pe. Această metodă are doi parametri: începem cu numele evenimentului pe care îl ascultăm: în acest caz, asta e "SomeEvent". Dar, desigur, ar putea fi orice și, de obicei, veți alege ceva mai bun. Al doilea parametru este funcția care va fi apelată la apariția evenimentului. Asta e tot ce este necesar pentru stabilirea unui eveniment.

Acum, pentru a declanșa evenimentul, treceți numele evenimentului la EventEmitter instanțe emite metodă. Aceasta este ultima linie a codului de mai sus. Dacă executați acel cod, veți vedea că vom trimite textul în consola.

Aceasta este cea mai de bază utilizare a unui EventEmitter. Puteți include, de asemenea, date când se declanșează evenimente:

 ee.emit ("utilizator nou", userObj);

Acesta este un singur parametru de date, dar puteți include cât doriți. Pentru a le folosi în funcția de gestionare a evenimentului, luați-i doar ca parametri:

 ee.on ("utilizator nou", funcție (date) // utilizați datele aici);

Înainte de a continua, permiteți-mi să clarific o parte din EventEmitter funcționalitate. Putem avea mai mult de un ascultător pentru fiecare eveniment; pot fi atribuite mai mulți ascultători de evenimente (toate cu pe), iar toate funcțiile vor fi apelate când evenimentul este declanșat. În mod implicit, Nodul permite cel mult zece ascultători dintr-un eveniment dintr-o dată; dacă sunt create mai multe, nodul va emite un avertisment. Cu toate acestea, putem schimba această sumă utilizând setMaxListeners. De exemplu, dacă executați acest lucru, ar trebui să vedeți un avertisment tipărit deasupra ieșirii:

 ee.on ("someEvent", funcția () console.log ("evenimentul 1");); ee.on ("someEvent", funcția () console.log ("eveniment 2");); ee.on ("someEvent", funcția () console.log ("evenimentul 3");); ee.on ("someEvent", funcția () console.log ("evenimentul 4");); ee.on ("someEvent", funcția () console.log ("evenimentul 5");); ee.on ("someEvent", funcția () console.log ("evenimentul 6");); ee.on ("someEvent", funcția () console.log ("evenimentul 7");); ee.on ("someEvent", funcția () console.log ("evenimentul 8");); ee.on ("someEvent", funcția () console.log ("evenimentul 9");); ee.on ("someEvent", funcția () console.log ("evenimentul 10");); ee.on ("someEvent", funcția () console.log ("eveniment 11");); ee.emit ( "someEvent");

Pentru a seta numărul maxim de spectatori, adăugați această linie deasupra ascultătorilor:

 ee.setMaxListeners (20);

Acum, când o executați, nu veți primi un avertisment.


Alte EventEmitter metode

Există și alte câteva EventEmitter metodele pe care le veți găsi utile.

Iată unul elegant: o singura data. Este la fel ca și pe cu excepția faptului că funcționează doar o singură dată. După ce a fost chemat pentru prima dată, ascultătorul este eliminat.

 ee.once ("firstConnection", funcția () console.log ("Nu veți mai vedea acest lucru din nou");); ee.emit ( "firstConnection"); ee.emit ( "firstConnection");

Dacă executați acest lucru, veți vedea mesajul o singură dată. A doua emisiune a evenimentului nu este luată de nici un ascultător (și asta este bine, apropo), pentru că o singura data ascultător a fost eliminat după ce a fost folosit o singură dată.

Vorbind despre eliminarea ascultătorilor, putem face acest lucru în mod manual, în câteva moduri. În primul rând, putem elimina un singur ascultător cu removeListener metodă. Este nevoie de doi parametri: numele evenimentului și funcția de ascultător. Până acum, am folosit funcții anonime ca ascultători. Dacă vrem să putem scoate un ascultător mai târziu, va trebui să fie o funcție cu un nume pe care îl putem referi. Putem folosi asta removeListener - metoda de duplicare a efectelor o singura data metodă:

 funcția onlyOnce () console.log ("Nu veți mai vedea niciodată acest lucru"); ee.removeListener ("firstConnection", onlyOnce);  ee.on ("firstConnection", onlyOnce) ee.emit ("firstConnection"); ee.emit ( "firstConnection");

Dacă executați acest lucru, veți vedea că are același efect ca și o singura data.

Dacă doriți să eliminați toți ascultătorii legați de un eveniment dat, puteți utiliza removeAllListeners; doar treceți numele evenimentului:

 ee.removeAllListeners ( "firstConnection");

Pentru a elimina toți ascultătorii pentru toate evenimentele, apelați funcția fără parametri.

ee.removeAllListeners ();

Există o ultimă metodă: ascultător. Această metodă ia numele unui eveniment ca parametru și returnează o matrice a tuturor funcțiilor care asculta pentru acel eveniment. Iată un exemplu de asta, pe baza noastră doar o data exemplu:

 funcția onlyOnce () console.log (ee.listeners ("firstConnection")); ee.removeListener ("firstConnection", onlyOnce); console.log (ee.listeners ( "firstConnection"));  ee.on ("firstConnection", onlyOnce) ee.emit ("firstConnection"); ee.emit ( "firstConnection");

Vom termina această secțiune cu un pic de meta-ness. Al nostru EventEmitter instanța în sine arde două evenimente proprii, pe care le putem asculta: una când noi creăm noi ascultători și una când le îndepărtăm. Vezi aici:

 ee.on ("newListener", funcția (evtName, fn) console.log ("New Listener:" + evtName);); ee.on ("removeListener", funcția (evtName) console.log ("Removal Listener:" + evtName);); funcția foo ()  ee.on ("save-user", foo); ee.removeListener ("salvați-utilizator", foo);

Făcând acest lucru, veți vedea ascultătorii noștri atât pentru noi ascultători, cât și pentru ascultători eliminați, iar noi primim mesajele pe care le așteptam.

Deci, acum că am văzut toate metodele EventEmitter exemplu, să vedem cum funcționează împreună cu alte module.

EventEmitter Module interioare

Din moment ce EventEmitter clasa este doar regulat JavaScript, are sens perfect că poate fi utilizat în cadrul altor module. În interiorul propriilor module JavaScript, puteți crea EventEmitter instanțe și să le folosească pentru a face față evenimentelor interne. E simplu, totuși. Mai interesant ar fi să creezi un modul care să moștenească EventEmitter, astfel încât să putem folosi funcționalitatea sa ca parte a API-ului public.

De fapt, sunt construite module Nod care fac exact acest lucru. De exemplu, ați putea fi familiarizat cu http modul; acesta este modulul pe care îl veți utiliza pentru a crea un server web. Acest exemplu de bază arată modul în care pe metodă a EventEmitter clasa a devenit parte din http.Server clasă:

 var http = necesită ("http"); serverul var = http.createServer (); server.on ("request", funcția (req, res) res.end ("acesta este răspunsul");); server.listen (3000);

Dacă executați acest fragment, procesul va aștepta o solicitare; poti sa te duci la http: // localhost: 3000 și veți primi răspunsul. Când instanța de server primește cererea de la browserul dvs., acesta emite un mesaj "cerere" eveniment, un eveniment pe care ascultătorul nostru îl va primi și îl poate acționa.

Deci, cum putem crea o clasă de la care să moștenească EventEmitter? De fapt, nu este așa de dificil. Vom crea un simplu listei de utilizatori clasă, care gestionează obiectele utilizatorului. Deci, într-un userlist.js fișier, vom începe cu acest lucru:

 var util = necesită ("util"); var EventEmitter = necesită ("evenimente") EventEmitter;

Avem nevoie de UTIL modul de a ajuta cu moștenirea. Apoi, avem nevoie de o bază de date: în loc să folosim o bază de date actuală, totuși, vom folosi un obiect:

 var id = 1; var id = utilizatori: id: id ++, nume: "Joe Smith", ocupație: "developer" id: id ++, , numele: "John Henry", ocupație: "designer"];

Acum, putem crea modulul nostru. Dacă nu sunteți familiarizat cu modulele Node, iată cum funcționează: orice JavaScript pe care îl scriem în acest fișier este citit numai din interiorul fișierului, în mod implicit. Dacă vrem să facem parte din API-ul public al modulului, îl facem proprietatea module.exports, sau să atribuiți un obiect sau o funcție complet nouă module.exports. Să o facem:

 funcția UserList () EventEmitter.call (aceasta); 

Aceasta este funcția constructor, dar nu este funcția obișnuită a constructorului JavaScript. Ce facem aici este utilizarea lui apel metoda pe EventEmitter constructor pentru a rula această metodă pe noul listei de utilizatori obiect (care este acest). Dacă trebuie să facem orice altă inițializare a obiectului nostru, am putea să o facem în interiorul acestei funcții, dar asta e tot ce vom face acum.

Moștenirea constructorului nu este însă suficientă; de asemenea, trebuie să moștenim prototipul. Aici este locul unde UTIL modulul vine.

 util.inherit (UserList, EventEmitter);

Acest lucru va adăuga tot ce este pe EventEmitter.prototype la UserList.prototype; acum, ale noastre listei de utilizatori instanțele vor avea toate metodele unui EventEmitter instanță. Dar vrem să adăugăm și mai multe, bineînțeles. Vom adăuga o Salvați , pentru a ne permite să adăugăm noi utilizatori.

 UserList.prototype.save = funcție (obj) obj.id = id ++; database.users.push (obj); this.emit ("user-save", obj); ;

Această metodă are ca obiectiv salvarea noastră "Bază de date": adaugă un id și îl împinge în matricea utilizatorilor. Apoi emite „Salvat-utilizator“ eveniment și trece obiectul ca date. Dacă aceasta ar fi o bază de date reală, salvarea ar fi probabil o sarcină asincronă, ceea ce înseamnă că pentru a lucra cu înregistrarea salvată, va trebui să acceptăm un apel invers. Alternativa la aceasta este de a emite un eveniment, așa cum facem. Acum, dacă vrem să facem ceva cu înregistrarea salvată, putem doar să ascultăm evenimentul. Vom face asta într-o secundă. Hai să închidem listei de utilizatori

 UserList.prototype.all = funcția () retur database.users; ; module.exports = UserList;

Am adăugat încă o metodă: una simplă care returnează toți utilizatorii. Apoi, noi atribuim listei de utilizatori la module.exports.

Acum, să vedem acest lucru în uz; într-un alt dosar, să zicem test.js. Adăugați următoarele:

 var UserList = necesită ("./ lista de utilizatori"); utilizatori var = noul UserList (); users.on ("utilizator-salvat", funcție (utilizator) console.log ("salvat:" + user.name + "(" + user.id + ")); users.save (nume: "Jane Doe", ocupație: "manager"); users.save (nume: "John Jacob", ocupație: "dezvoltator");

După ce ne cerem noul modul și creăm o instanță a acestuia, ascultăm pentru „Salvat-utilizator“ eveniment. Apoi, putem merge mai departe și să salvăm câțiva utilizatori. Când executăm acest lucru, veți vedea că primim două mesaje, tipărirea numelor și a numelor de înregistrări pe care le-am salvat.

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

Desigur, acest lucru ar putea să acționeze invers: am putea folosi pe metoda din interiorul clasei noastre și emite în afara sau în interiorul sau în afară. Dar acesta este un bun exemplu pentru cum ar putea fi făcut.


Concluzie

Așa este Node EventEmitter clasa de lucrări. Mai jos veți găsi link-uri către documentația nodului pentru unele dintre lucrurile despre care am vorbit.

  • Nod Evenimente Module
  • Nod Util Modul
  • Nod Sursa agentului HTTP - Aceasta arată modelul de mostenire folosit.
Cod