Servicii vs. fabrici în Angular

EDIT 2016. Rețineți că această postare, care este o reluare a unei postări din 2015, se referă la Angular 1. Nu mă mai ocup de frontend, așa că nu garantez că această postare este relevantă pentru Angular 2 ;).

Unul dintre colegii mei de clasă de la Hack Reactor și cu mine am construit recent un calculator pentru tratamentul hipertensiunii arteriale pentru Moxe Health, o companie interesantă de Rock Health care construiește un sistem de integrare a bazei de date și un API care va permite oricărui dezvoltator să acceseze dosarele medicale electronice ale oricărui spital din rețeaua Moxe. Sunt încântat să vorbesc despre Moxe și despre proiect într-o altă postare. Am construit front-end-ul aplicației în Angular, un framework front-end puternic, cu data binding și alte caracteristici impresionante. Un lucru care a fost derutant a fost când să folosim servicii vs. fabrici. Stack Overflow are un fir de discuție bun despre diferența dintre cele două, dar omite câteva analogii care cred că sunt utile pentru dezvoltatorii care încă își cimentează cunoștințele de Javascript.

În această postare, veți învăța diferența dintre cele două.

TLDR – fabricile și serviciile au cam aceeași funcționalitate în ceea ce privește capacitatea lor de a instanția și încapsula metode și proprietăți, la fel cum modelele de instanțiere funcțională și de instanțiere pseudoclasică au abilități similare. Nu există nicio preferință în comunitatea Angular pentru utilizarea uneia sau a celeilalte. Rețetele de fabrici și servicii sunt doar zahăr sintactic peste rețeta furnizorului. Așadar, întrebarea pe care ar trebui să v-o puneți nu este, de obicei, „ar trebui să folosesc fabrici sau servicii?”, ci „ar trebui să folosesc instanțierea funcțională sau instanțierea pseudoclasică?”.”

În afară de această înțelegere la nivel înalt, cea mai semnificativă diferență este că, ca urmare a diferenței dintre modelele lor de instanțiere, fabricile pot returna primitive și funcții, dar serviciile nu pot.

Primitive, funcții și obiecte, oh, Doamne!

Vezi acest JSFiddle. Credit lui Epokk pentru că a furnizat cea mai mare parte a codului. Am făcut câteva modificări care, din nou, ajută cu adevărat dezvoltatorii noi în Angular să aprofundeze diferențele de aici. Dacă sunteți nou în JSFiddle, este un instrument care vă permite să testați cu ușurință interacțiunile dintre fișierele dvs. javascript, html și css. Astfel, vă puteți juca cu codul, iar acesta nu va suprascrie codul original din link.

Atât serviciul, cât și fabrica din acest exemplu au aceeași funcționalitate de returnare a șirului „Hello World!”. Diferența constă în modul în care o fac.

Serviciul instanțiază un obiect și atribuie funcția care returnează „Hello World!” proprietății „sayHello” a acelui obiect:

this.sayHello = function() { return "Hello, World!" };

Metoda este apoi invocată în controler: helloWorldFromService.sayHello().

Fabrica returnează o funcție care returnează „Hello World!”:

return function() { return "Hello, World!" };

Funcția este apoi invocată în controler: helloWorldFromFactory(). Observați cum referința fabricii indică funcția returnată, mai degrabă decât proprietatea unui obiect a cărui valoare este o funcție, ca în exemplul serviciului. Un serviciu nu ar putea face niciodată acest lucru, deoarece un serviciu trebuie să instanțieze un obiect gol a cărui referință în corpul funcției de serviciu este „this”. Serviciile returnează întotdeauna obiecte.

Aici este partea din fabrici care poate fi confuză. Fabrica poate, de asemenea, să returneze un obiect care are o metodă ‘sayHello’, la fel ca serviciul:

return { sayHello: function() { return "Hello, World!" } };

Ceea pe care o veți invoca în controler exact așa cum ați invoca funcția sayHello a serviciului: helloWorldFromFactory.sayHello().

Cel din urmă format de fabrică este util atunci când doriți să aveți mai multe metode într-o fabrică:

return { sayHello: function() { return "Hello, World!" }, sayGoodbye: function() { return "Goodbye, World!" } };

Încă o dată, cheia aici este să nu vă lăsați prins de faptul că codificați în Angular și să vă amintiți că diferențele dintre servicii și fabrici sunt, în cea mai mare parte, aceleași ca și diferențele dintre instanțierea pseudoclasică și instanțierea funcțională.

Cod sursă pentru curioși

Iată codul sursă Angular, demonstrând că serviciile & fabricile sunt suprapuse peste caracteristica mai generală a furnizorilor:

//provider function provider(name, provider_) { assertNotHasOwnProperty(name, 'service'); if (isFunction(provider_) || isArray(provider_)) { provider_ = providerInjector.instantiate(provider_); } if (!provider_.$get) { throw $injectorMinErr('pget', "Provider '{0}' must define $get factory method.", name); } return providerCache = provider_; } //factory function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } //service function service(name, constructor) { return factory(name, ); }

Atât serviciile cât și fabricile creează singletoni. Modele de bază de moștenire funcțională vs. pseudoclasică aici. Fabrica returnează orice returnează factoryFn.

Serviciul returnează o instanță a unei pseudoclase. Constructorul pseudo-clasei este transmis constructorului de servicii al lui Angular service(). Faptul că constructorul este transmis serviciului de construire a serviciului (return $injector.instantiate(constructor)) poate fi derutant, dar gândiți-vă că este return new constructor().

Codificare fericită!

Leave a Reply