For noen nybegynnere, kan noen tydelig forklare forskjellen mellom Service, Factory og Provider i AngularJS?


Svar 1:

AngularJS: Forskjell mellom Service vs Provider vs Factory

Hvis du søker etter dette, er det sannsynligvis fordi du prøver å finne ut hvilken som er den rette du kan bruke. Eller fordi du har kommet over de tre av dem og prøver å bestemme forskjellen fordi de virker like.

Hvis du tror de er like - har du rett. De er veldig like. Faktisk er de alle de samme tingene.

De er alle tilbydere. Fabrikken og tjenesten er bare spesielle tilfeller av leverandøren, men du kan oppnå alt du vil bruke bare leverandøren. Jeg skal vise deg.

Tilbyderen

Vi skal lage en leverandør som returnerer en verdi og ganske enkelt vise den verdien, vil du gjøre dette:

var mod = angular.module ("MyModule", []); mod.provider ("myProvider", funksjon () {dette. $ get = function () {return "My Value";};}); mod.controller ("MyController", funksjon (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); CONSOLE OUTPUT MyController - myProvider: My Value

Et fungerende interaktivt eksempel finner du på: JS Fiddle.

Der, så en "leverandør" i kjernen lar deg "gi" en verdi. Den verdien kan være hva som helst. I dette tilfellet er det en streng med verdien "My Value", men den kunne lett ha vært en funksjon eller et objekt.

Merk i ytterligere kodeprøver jeg vil ekskludere tag og definisjonen av mod for å holde kodeutdragene korte og like.

Angular får bare verdien en gang - noen gang

Vær oppmerksom på at kantete bare "får" verdien en gang, uansett hvor mange ganger leverandøren blir injisert. Det betyr at det kaller $ get () bare en gang noensinne, lagrer verdien levert av $ get (), og gir deg den samme lagrede verdien hver gang.

For å vise deg hva jeg mener, vil jeg opprette en annen kontroller og injisere leverandøren igjen med en konsollerklæring, slik at du kan se hva som skjer.

mod.provider ("myProvider", funksjon () {dette. $ get = function () {console.log ("MyProviderFunction. $ get () kalt."); // LEGG TIL denne linjen returnerer "My Value";}; }); mod.controller ("MyController", funksjon (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); mod.controller ("MyController2", funksjon (myProvider) {// LAGT denne kontrolleren console.log ("MyController2 - myProvider:" + myProvider);}); CONSOLE OUTPUT MyProviderFunction. $ Få () ringt. MyController - myProvider: My Value MyController2 - myProvider: My Value

Åpent i JS Fiddle

Som du kan se ble $ get () -funksjonen bare kalt en gang.

Merk at vi skrev en haug med kode for leverandøren bare med det formål å lage en metode som heter $ get (). Hvorfor ikke i stedet for å gi kantete en funksjon som definerer en annen funksjon, hvorfor ikke bare gi den den funksjonen vi ønsker å kjøre direkte i stedet? Du kan vel, det er det Angular kaller en fabrikk.

En fabrikk

Med en fabrikk gir du bare funksjonsorganet for $ get-metoden og Angular gjør resten. Nedenfor ser du hvordan den nye koden ser ut, for du vil se at den oppfører seg nøyaktig den samme.

mod.factory ("myProvider", funksjon () {// ENDRE "leverandør" til "fabrikk" console.log ("Fabrikkfunksjon kalt."); returner "Min verdi";}); mod.controller ("MyController", funksjon (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); mod.controller ("MyController2", function (myProvider) {console.log ("MyController2 - myProvider:" + myProvider);}); CONSOLE OUTPUT Fabrikkfunksjon kalt. MyController - myProvider: My Value MyController2 - myProvider: My Value

Åpent i JS Fiddle

Nå lurer du kanskje på hvorfor skulle du noen gang bruke en leverandør hvis du kan oppnå det samme med en fabrikk med mindre kode. Det er et par grunner, og jeg vil gå nærmere inn på det senere, akkurat nå vil jeg være tro mot tittelen på dette innlegget og adressere forskjellen mellom disse to (leverandør og fabrikk) og en tjeneste.

Så langt har vi returnert en enkel strengverdi, men i praksis er det vi sannsynligvis vil returnere mesteparten av tiden et objekt. Vel, det vil ikke endre vårt eksempel veldig mye, vi kan veldig enkelt bytte ut strengen vi returnerer med et objekt i stedet.

La oss for eksempel gjøre det ved å returnere et objekt som inneholder en funksjon som heter getValue (). Nå er det flere måter du kan opprette et objekt i JavaScript, vi skal bruke "Object Constructor" -tilnærmingen der vi oppretter en funksjon som fyller et objekt med egenskaper og funksjoner og bruker det nye nøkkelordet for å instantisere det.

funksjon MyObject () {// LAGT objektkonstruktøren vår this.getValue = function () {return "My Value"; }; } mod.factory ("myProvider", funksjon () {console.log ("Fabrikkfunksjon kalt."); returner nye MyObject (); // CREATE en forekomst av objektet vårt}); mod.controller ("MyController", function (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ()); // ENDRE for å ringe getValue ()}); mod.controller ("MyController2", function (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ()); // ENDRE å kalle getValue ()}); CONSOLE OUTPUT Fabrikkfunksjon kalt. MyController - myProvider: My Value MyController2 - myProvider: My Value

Åpent i JS Fiddle

Nå vil jeg lage en liten finjustering til dette fordi det vil føre fint inn i neste konsept. I vårt eksempel oppretter vi "Object Constructor" -funksjonen MyObject (), men siden vi bare instantiserer den på ett sted, kan vi bruke en anonym funksjon i stedet.

Dette er en veldig liten finjustering. Istedenfor dette:

funksjon MyObject () {this.getValue = function () {return "My Value"; }; } mod.factory ("myProvider", funksjon () {console.log ("Fabrikkfunksjon kalt."); returner nye MyObject ();});

Vi gjør dette:

mod.factory ("myProvider", function () {console.log ("Factory function called."); return new function () {// INLINED our object constructor this.getValue = function () {return "My Value"; };};});

Så det hele ser nå ut slik:

mod.factory ("myProvider", function () {console.log ("Factory function called."); return new function () {// INLINED our object constructor this.getValue = function () {return "My Value"; };};}); mod.controller ("MyController", funksjon (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ());}); mod.controller ("MyController2", function (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ());});

Åpent i JS Fiddle

Siden hele fabrikken består av et enkelt objekt, ville det ikke være fint om vi bare kunne gi Angular objektkonstruktørfunksjonen i stedet for å måtte skrive den funky fabrikken. Vel, du er heldig, det er akkurat hva en tjeneste er.

Til tjeneste

Her er den samme koden bortsett fra å bruke en tjeneste i stedet for en fabrikk.

mod.service ("myProvider", funksjon () {// ENDRE "fabrikk" til "service" // MERK at den eneste funksjonen som blir bestått er objektkonstruktøren fra før this.getValue = function () {return "My Value" ;};}); mod.controller ("MyController", funksjon (myProvider) {console.log ("MyController - myProvider:" + myProvider.getValue ());}); mod.controller ("MyController2", function (myProvider) {console.log ("MyController2 - myProvider:" + myProvider.getValue ());}); CONSOLE OUTPUT MyController - myProvider: My Value MyController2 - myProvider: My Value

Åpent i JS Fiddle

Tilbyder vs fabrikk vs tjeneste

Så i sammendrag er leverandør, fabrikk og tjeneste alle leverandører. En fabrikk er et spesielt tilfelle av en leverandør når alt du trenger i leverandøren din er en $ get () -funksjon. Den lar deg skrive den med mindre kode. En tjeneste er et spesielt tilfelle av en fabrikk når du vil returnere en forekomst av et nytt objekt, med samme fordel med å skrive mindre kode.

Når skal man bruke det ene mot det andre?

Svaret er at du bruker den mest spesialiserte versjonen som oppnår målet ditt. Si for eksempel at du returnerer et eksisterende objekt definert et annet sted som tar konstruktørargumenter. Du kan ikke sende argumenter til tjenesten, så du vil ringe med en fabrikk i stedet.

mod.factory ("myProvider", funksjon () {console.log ("Fabrikkfunksjon kalt."); returner nye SomeMessageBoxClass ("tilpasset argument");});

En av hovedfaktorene for å avgjøre mellom en leverandør og fabrikk er om du vil kunne konfigurere objektet som blir generert før det genereres. Dette gjør du ved å ringe module.config () og få en instans til leverandøren selv (i stedet for objektet som tilbakeleveres av leverandøren). Du gjør dette ved å legge til "leverandør" på slutten av leverandørens navn når du injiserer det.

Her er et eksempel på hvordan du gjør det:

mod.provider ("myProvider", funksjon () {this.value = "My Value"; this.setValue = function (newValue) {this.value = newValue;}; dette. $ get = function () {return this. verdi;};}); mod.controller ("MyController", funksjon (myProvider) {console.log ("MyController - myProvider:" + myProvider);}); mod.config (funksjon (myProviderProvider) {// ADDED config seksjon // Legg merke til den ekstra "Provider" -suffikset myProviderProvider.setValue ("New Value");});

Dette dekker når du skal bruke de tre leverandørene: leverandør, fabrikk og service. Det er en tilleggsleverandør som ikke ble nevnt her, som er enda en spesiell sak, og det er verdileverandøren.

Hvis du husker da vi først presenterte fabrikkleverandøren ovenfor, ga vi det enkle eksemplet på å returnere en strengverdi. Det så ut slik:

mod.factory ("myProvider", funksjon () {return "My Value";});

Vel, vi kunne faktisk ha gjort det ved å bruke verdileverandøren i stedet, og fordelen er at du kan gjøre det med mindre kode. Koden nedenfor gjør det samme som koden over:

mod.value ("myProvider", "My Value");

Så når vil du bruke det ene mot det andre? Antagelig vil du bruke fabrikkprovideren når du vil beregne verdien basert på noen andre data, for eksempel data fra en annen verdiforhandler eller en ekstern kilde. Og / eller når du vil beregne verdien hvis og bare når den først blir bedt om det. Her er noen eksempler:

// Eksempel der fabrikk er avhengig av en "verdi" -leverandør mod.value ("multiple", 3); mod.factory ("verdi", funksjon (multiple) {return 10 * multiple;}); // Eksempel der fabrikk er avhengig av ekstern data mod.factory ("verdi", funksjon (flere) {var multiple = getDateFromExternalPage (); return 10 * multiple;});

Indikerte jeg at verdien var den eneste andre leverandøren? Vel, jeg løy, det er en annen som er veldig lik verdi med to mindre forskjeller. Den leverandøren kalles konstant.

Forskjellen mellom verdi og konstant er at en verdi spesifisert ved bruk av konstant er tilgjengelig i konfigurasjonsfasen. Du husker kanskje fra tidligere at jeg nevnte at leverandøren var tilgjengelig fra konfigurasjonsfasen, men service og fabrikk var det ikke.

Vel, det er det samme for verdi og konstant. konstant er tilgjengelig fra konfigurasjonsfasen og verdien er ikke. Den andre forskjellen er som navnet tilsier at du ikke kan endre verdien på en konstant. Den første verdien du tildeler den, er verdien den holder, hvis du prøver å tildele den en annen verdi senere, vil den bli ignorert.

Her er et eksempel:

mod.value ("myValue", "First Assignment"); mod.value ("myValue", "Second Assignment"); mod.constant ("myConstant", "First Assignment"); mod.constant ("myConstant", "Second Assignment"); mod.controller ("MyController", funksjon (myValue, myConstant) {console.log ("myValue:" + myValue); console.log ("myConstant:" + myConstant);}); CONSOLE OUTPUT myValue: Second Assignment myConstant: First Assignment

Her er et sammendrag av når du skal bruke hver:

verdi

Du gir en enkel bokstavelig verdi.

mod.value ("myValue", 10);
    

konstant

Du må kunne få tilgang til den verdien i konfigurasjonsfasen. (bruker .config ())

mod.constant ("myValue", 10); mod.config (funksjon (myValue) {console.log (myValue);});

fabrikk

Verdien du oppgir må beregnes basert på andre data.

mod.factory ("myFactory", funksjon () {return 10;});
        

service

Du returnerer et objekt med metoder.

mod.service ("myService", funksjon () {var name = "Bob"; this.setName = function (newName) {this.name = newName;}; this.getName = function () {return this.name;} });
        

forsørger

Du vil kunne konfigurere objektet som skal opprettes i konfigurasjonsfasen før det opprettes.

mod.provider ("greeter", function () {var name; this.setName = function (newName) {name = newName;}; dette. $ get = function () {return new function () {this.sayHi = function () {console.log ("Hei" + navn;};};};}); mod.config (funksjon (greeterProvider) {greeterProvider.setName ("John");});
        

For å kjøre punktet hjem en siste gang her, er et bilde av en leverandør med fabrikk-, verdi- og servicepartier uthevet:


Svar 2:

Internt bruker AngularJS Factory for å opprette Service Object og bruker Provider for å opprette Factory Object.

En fabrikk gjør det,

  1. Opprett et objekt / forekomstKonstruer / initialiser det opprettede objektet / instancereturn det opprettede objektet / forekomsten

For å angi kontekst, vurder Angular Factory som abstrakt fabrikkdesignmønster. AngularJS gir deg muligheten til å lage et objekt du ønsker, ved å bruke din fabrikkmetode, returnere det opprettede objektet for applikasjonen din til å bruke som tjeneste.

Nedenfor eksempel har du valg mellom to betalingsportaler, noen som bruker koden / biblioteket, fabrikkmetoden din kan velge om du vil opprette Paypal eller Stripe-objekt. Dette ligner veldig på Abstract Factory, brukerne av paymentService vet ikke hvilken tjeneste som er brukt til betalingsport.

var myModule = angular.module ('myModule', []); myModule.constant (“PaymentGatewayName”, “Stripe”); // eller "Paypal" myModule.factory ('paymentService', funksjon (PaymentGatewayName) {var paymentService; // du bestemmer hvilket objekt du vil lage basert på forretningsbehov // StripeGateway og PaypalGateway er JavaScript-klasser // inneholder Gateway-spesifikk implementering hvis ( PaymentGatewayName == "Stripe") {paymentService = new StripeGateway (); // tilpasset kode for å initialisere stripe gateway} annet (PaymentGatewayName == "Paypal") {PaymentService = new PaypalGateway (); // tilpasset kode for å initialisere paypal} / / tilpasset kode for å initialisere PaymentService returnere PaymentService;});

En servicekode ser slik ut, du legger merke til “dette” nøkkelordet, det betyr at objekt allerede er opprettet for deg av Angular Core, du kontrollerer ikke mer objektoppretting.

var myModule = angular.module ('myModule', []); myModule.service ('Cache', funksjon () {var localVariable = ""; // kan ikke nås utenfor dette.cacheSize = 5; // 5 MB this.objectsSize = 1000; // max 1000 objekter this.put = function (nøkkel, verdi) {...} this.get = funksjon (få) {retur ...}});

Svar 3:

Det store spørsmålet i AngularJS: Service vs Factory v / s Provider. Hva skal jeg bruke?

Det er mange ressurser på internett som diskuterer emnet. Det viser seg at dette spørsmålet fortsatt dukker opp hver uke eller så på forskjellige kanaler, og selv etter å ha lest de ti beste svarene på StackOverflow, er det fremdeles ikke veldig tydelig.

Hvis du tror de er like - har du rett. De er veldig like. Faktisk er de alle de samme tingene. De er alle tilbydere.

Les hele artikkelen -> AngularJS: Service v / s Factory v / s Provider - Gjør deg klar til intervju om 15 minutter