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 ceDeci, 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.
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.
EventEmitter
metodeExistă ș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 interioareDin 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.
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.