Tjänster kontra fabriker i Angular

REDIGERA 2016. Observera att det här inlägget, som är en ompostning av ett inlägg från 2015, handlar om Angular 1. Jag sysslar inte med frontend längre så inga garantier för att det här inlägget är relevant för Angular 2 ;).

En av mina Hack Reactor-klasskamrater och jag byggde nyligen en kalkylator för behandling av högt blodtryck för Moxe Health, ett spännande Rock Health-företag som håller på att bygga upp ett system för databasintegration och ett API som gör det möjligt för vilken utvecklare som helst att få tillgång till de elektroniska medicinska journalerna från vilket sjukhus som helst i Moxe’s nätverk. Jag är glad att få prata om Moxe och projektet i ett annat inlägg. Vi byggde appens front-end i Angular, ett kraftfullt front-end ramverk med databindning och andra fantastiska funktioner. En sak som var förvirrande var när man skulle använda tjänster kontra fabriker. Stack Overflow har en bra tråd om skillnaden mellan de två, men den utelämnar några analogier som jag tror är användbara för utvecklare som fortfarande cementerar sina Javascript-kunskaper.

I det här inlägget kommer du att lära dig skillnaden mellan de två.

TLDR – Factories och services har ganska mycket samma funktionalitet när det gäller deras förmåga att instansiera och enscapsulera metoder och egenskaper, precis som funktionell instansiering och pseudoklassiska instansieringsmönster har liknande förmågor. Det finns ingen preferens i Angular-communityt för att använda det ena eller det andra. Fabriks- och tjänsterecept är bara syntaktiskt socker ovanpå providerreceptet. Så frågan du bör ställa dig själv är vanligtvis inte ”ska jag använda fabriker eller tjänster?” utan ”ska jag använda funktionell instantiering eller pseudoklassisk instantiering?”.”

Och förutom denna förståelse på hög nivå är den viktigaste skillnaden att som ett resultat av skillnaden i deras instansieringsmönster kan fabriker returnera primitiver och funktioner, men inte tjänster.

Primitiver, funktioner och objekt, oj då!

Kolla in den här JSFiddle. Epokk har fått beröm för att ha tillhandahållit större delen av koden. Jag gjorde ett par ändringar som återigen verkligen hjälper utvecklare som är nya i Angular att borra ner på skillnaden här. Om du är ny på JSFiddle är det ett verktyg som gör att du enkelt kan testa interaktioner mellan dina javascript-, html- och css-filer. Så du kan leka med koden utan att den ursprungliga koden i länken skrivs över.

Både tjänsten och fabriken i det här exemplet har samma funktionalitet, nämligen att returnera strängen ”Hello World!”. Skillnaden är hur de gör det.

Tjänsten instansierar ett objekt och tilldelar funktionen som returnerar ”Hello World!” till ”sayHello”-egenskapen för det objektet:

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

Metoden åberopas sedan i controllern: helloWorldFromService.sayHello().

Fabriken returnerar en funktion som returnerar ”Hello World!”:

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

Funktionen anropas sedan i styrenheten: helloWorldFromFactory(). Observera hur fabrikens referens pekar på den returnerade funktionen, snarare än på egenskapen för ett objekt vars värde är en funktion, som i tjänsteexemplet. En tjänst skulle aldrig kunna göra detta, eftersom en tjänst måste instantiera ett tomt objekt vars referens i tjänstens funktionskropp är ”this”. Tjänster returnerar alltid objekt.

Här är den del av factories som kan vara förvirrande. Fabriken kan också returnera ett objekt som har en metod ”sayHello”, precis som tjänsten:

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

Vad du skulle åberopa i controllern precis som du skulle åberopa tjänstens sayHello-funktion: helloWorldFromFactory.sayHello().

Det senare fabriksformatet är användbart när du vill ha flera metoder i en fabrik:

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

Nyckeln här är återigen att inte fastna i det faktum att du kodar i Angular, och att komma ihåg att skillnaderna mellan tjänster och fabriker till största delen är desamma som skillnaderna mellan pseudoklassisk instantiering och funktionell instantiering.

Källkod för den nyfikne

Här är Angular-källkoden som visar att services & factories läggs ovanpå den mer generella providers-funktionen:

//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, ); }

Både service och factory skapar singletons. Grundläggande funktionella vs. pseudoklassiska arvsmönster här. Fabriken returnerar vad factoryFn returnerar.

Tjänsten returnerar en instans av en pseudoklass. Pseudoklassens konstruktör skickas till Angulars tjänstebyggare service(). Det faktum att konstruktören skickas till tjänstebyggaren service (return $injector.instantiate(constructor)) kan vara förvirrande, men tänk bara på det som return new constructor().

Happy coding!

Leave a Reply