Jakie są różnice pomiędzy a Service
, Provider
oraz Factory
w angularjs?
service.factory
. Nie chciałem dalej komplikować tego tematu.
Jakie są różnice pomiędzy a Service
, Provider
oraz Factory
w angularjs?
service.factory
. Nie chciałem dalej komplikować tego tematu.
Odpowiedzi:
Z listy mailingowej AngularJS otrzymałem niesamowity wątek, który wyjaśnia obsługę kontra fabryka kontra dostawca i sposób ich użycia. Kompilowanie odpowiedzi:
Składnia: module.service( 'serviceName', function );
Wynik: Gdy deklarujesz serviceName jako argument do wstrzyknięcia , otrzymasz instancję funkcji. Innymi słowy new FunctionYouPassedToService()
.
Składnia: module.factory( 'factoryName', function );
Wynik: deklarując nazwę_produktu jako argument do wstrzyknięcia, otrzymasz wartość zwracaną przez wywołanie odwołania do funkcji przekazanego do module.factory .
Składnia: module.provider( 'providerName', function );
Wynik: deklarując nazwę dostawcy jako argument do wstrzyknięcia , otrzymasz (new ProviderFunction()).$get()
. Funkcja konstruktora jest tworzona przed wywołaniem metody $ get - ProviderFunction
czy odwołanie do funkcji jest przekazywane do module.provider.
Zaletą dostawców jest to, że można je konfigurować podczas fazy konfiguracji modułu.
Widzieć tutaj podany kod.
Oto świetne dalsze wyjaśnienie Misko:
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
W takim przypadku wtryskiwacz po prostu zwraca wartość jaka jest. Ale co jeśli chcesz obliczyć wartość? Następnie skorzystaj z fabryki
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(b).toEqual(246);
}
Więc factory
jest funkcja odpowiedzialna za tworzenie wartości. Zauważ, że funkcja fabryczna może prosić o inne zależności.
Ale co, jeśli chcesz być bardziej OO i mieć klasę o nazwie Greeter?
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
Następnie, aby utworzyć wystąpienie, musisz napisać
provide.factory('greeter', function(a) {
return new Greeter(a);
});
Następnie moglibyśmy poprosić o „powitanie” w kontrolerze takim jak ten
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
Ale to jest zbyt trudne. Byłby to krótszy sposób na napisanie tegoprovider.service('greeter', Greeter);
Ale co, jeśli chcielibyśmy skonfigurować Greeter
klasę przed wstrzyknięciem? Wtedy moglibyśmy pisać
provide.provider('greeter2', function() {
var salutation = 'Hello';
this.setSalutation = function(s) {
salutation = s;
}
function Greeter(a) {
this.greet = function() {
return salutation + ' ' + a;
}
}
this.$get = function(a) {
return new Greeter(a);
};
});
Następnie możemy to zrobić:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter2.greet()).toEqual('Halo 123');
}
Na marginesie, service
, factory
, i value
są pochodzące od dostawcy.
provider.service = function(name, Class) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.instantiate(Class);
};
});
}
provider.factory = function(name, factory) {
provider.provide(name, function() {
this.$get = function($injector) {
return $injector.invoke(factory);
};
});
}
provider.value = function(name, value) {
provider.factory(name, function() {
return value;
});
};
toEqual
i greeter.Greet
to. Dlaczego nie użyć czegoś nieco bardziej realnego i powiązanego?
factory
/ service
/ provider
:var myApp = angular.module('myApp', []);
//service style, probably the simplest one
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
//factory style, more involved but more sophisticated
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
//provider style, full blown, configurable version
myApp.provider('helloWorld', function() {
this.name = 'Default';
this.$get = function() {
var name = this.name;
return {
sayHello: function() {
return "Hello, " + name + "!";
}
}
};
this.setName = function(name) {
this.name = name;
};
});
//hey, we can configure a provider!
myApp.config(function(helloWorldProvider){
helloWorldProvider.setName('World');
});
function MyCtrl($scope, helloWorld, helloWorldFromFactory, helloWorldFromService) {
$scope.hellos = [
helloWorld.sayHello(),
helloWorldFromFactory.sayHello(),
helloWorldFromService.sayHello()];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl">
{{hellos}}
</div>
</body>
this
zmienia kontekstu w $get
funkcji? - już nie odwołujesz się do dostawcy instancji w tej funkcji.
this
rzeczywistości nie zmienia kontekstu, ponieważ wywoływana jest funkcja new Provider()
. $ Get (), do której Provider
przekazywana jest funkcja app.provider
. To znaczy, że $get()
jest wywoływany jako metoda na skonstruowanej Provider
, więc this
będzie się odnosił Provider
tak, jak sugeruje to przykład.
Unknown provider: helloWorldProvider <- helloWorld
, uruchamiając to lokalnie? Komentując to, ten sam błąd dla pozostałych 2 przykładów. Czy jest jakaś ukryta konfiguracja dostawcy? (Angular 1.0.8) - Znaleziono: stackoverflow.com/questions/12339272/…
TL; DR
1) Gdy używasz fabryki , tworzysz obiekt, dodajesz do niego właściwości, a następnie zwraca ten sam obiekt. Po przekazaniu tej fabryki do kontrolera właściwości tego obiektu będą teraz dostępne w tym kontrolerze za pośrednictwem fabryki.
app.controller(‘myFactoryCtrl’, function($scope, myFactory){
$scope.artist = myFactory.getArtist();
});
app.factory(‘myFactory’, function(){
var _artist = ‘Shakira’;
var service = {};
service.getArtist = function(){
return _artist;
}
return service;
});
2) Gdy korzystasz z usługi , AngularJS tworzy ją za kulisami ze słowem kluczowym „new”. Z tego powodu dodasz właściwości do „tego”, a usługa zwróci „to”. Po przekazaniu usługi do kontrolera właściwości „this” będą teraz dostępne na tym kontrolerze za pośrednictwem usługi.
app.controller(‘myServiceCtrl’, function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service(‘myService’, function(){
var _artist = ‘Nelly’;
this.getArtist = function(){
return _artist;
}
});
3) Dostawcy są jedyną usługą, którą można przekazać do funkcji .config (). Skorzystaj z usługodawcy, jeśli chcesz udostępnić konfigurację całego modułu dla obiektu usługi przed udostępnieniem go.
app.controller(‘myProvider’, function($scope, myProvider){
$scope.artist = myProvider.getArtist();
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
app.provider(‘myProvider’, function(){
//Only the next two lines are available in the app.config()
this._artist = ‘’;
this.thingFromConfig = ‘’;
this.$get = function(){
var that = this;
return {
getArtist: function(){
return that._artist;
},
thingOnConfig: that.thingFromConfig
}
}
});
app.config(function(myProviderProvider){
myProviderProvider.thingFromConfig = ‘This was set in config’;
});
Non TL; DR
1)
Fabryki to najpopularniejszy sposób tworzenia i konfigurowania usługi. Naprawdę niewiele więcej niż mówi TL; DR. Wystarczy utworzyć obiekt, dodać do niego właściwości, a następnie zwrócić ten sam obiekt. Następnie, po przekazaniu fabryki do kontrolera, te właściwości obiektu będą teraz dostępne w tym kontrolerze przez fabrykę. Bardziej obszerny przykład znajduje się poniżej.
app.factory(‘myFactory’, function(){
var service = {};
return service;
});
Teraz wszelkie właściwości, które dołączamy do „usługi”, będą dostępne, gdy przekażemy „myFactory” do naszego kontrolera.
Dodajmy teraz trochę „prywatnych” zmiennych do naszej funkcji zwrotnej. Nie będą one bezpośrednio dostępne z poziomu kontrolera, ale w końcu skonfigurujemy metody getter / setter dla „service”, aby móc zmienić te „prywatne” zmienne w razie potrzeby.
app.factory(‘myFactory’, function($http, $q){
var service = {};
var baseUrl = ‘https://itunes.apple.com/search?term=’;
var _artist = ‘’;
var _finalUrl = ‘’;
var makeUrl = function(){
_artist = _artist.split(‘ ‘).join(‘+’);
_finalUrl = baseUrl + _artist + ‘&callback=JSON_CALLBACK’;
return _finalUrl
}
return service;
});
Tutaj zauważysz, że nie przypisujemy tych zmiennych / funkcji do „usługi”. Po prostu tworzymy je w celu późniejszego wykorzystania lub modyfikacji.
Teraz, gdy nasze zmienne pomocnicze / prywatne i funkcja są już na miejscu, dodajmy pewne właściwości do obiektu „service”. Cokolwiek nałożymy na „usługę”, może być użyte bezpośrednio w dowolnym kontrolerze, w którym przekazujemy „myFactory”.
Stworzymy metody setArtist i getArtist, które po prostu zwrócą lub ustawią artystę. Stworzymy również metodę, która wywoła interfejs API iTunes z naszym utworzonym adresem URL. Ta metoda zwróci obietnicę, która spełni się, gdy dane wrócą z interfejsu API iTunes. Jeśli nie masz dużego doświadczenia w korzystaniu z obietnic w AngularJS, zdecydowanie polecam głębokie zanurzenie się w nich.
Poniżej setArtist akceptuje wykonawcę i umożliwia ustawienie wykonawcy. getArtist zwraca wykonawcę. callItunes najpierw wywołuje makeUrl () w celu zbudowania adresu URL, którego będziemy używać z naszym żądaniem $ http. Następnie ustawia obiekt obietnicy, wysyła żądanie $ http z naszym ostatnim adresem URL, a ponieważ $ http zwraca obietnicę, jesteśmy w stanie wywołać .success lub .error po naszej prośbie. Następnie wypełniamy naszą obietnicę za pomocą danych iTunes lub odrzucamy ją komunikatem „Wystąpił błąd”.
app.factory('myFactory', function($http, $q){
var service = {};
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
service.setArtist = function(artist){
_artist = artist;
}
service.getArtist = function(){
return _artist;
}
service.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
return service;
});
Teraz nasza fabryka jest kompletna. Jesteśmy teraz w stanie wstrzyknąć „myFactory” do dowolnego kontrolera, a następnie będziemy mogli wywoływać nasze metody, które podłączyliśmy do naszego obiektu usługi (setArtist, getArtist i callItunes).
app.controller('myFactoryCtrl', function($scope, myFactory){
$scope.data = {};
$scope.updateArtist = function(){
myFactory.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myFactory.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
W powyższym kontrolerze wprowadzamy usługę „myFactory”. Następnie ustawiamy właściwości naszego obiektu $ scope danymi z „myFactory”. Jedynym trudnym kodem powyżej jest to, że nigdy wcześniej nie dotykałeś obietnic. Ponieważ callItunes zwraca obietnicę, jesteśmy w stanie użyć metody .then () i ustawić wartość $ scope.data.artistData tylko wtedy, gdy nasza obietnica zostanie wypełniona danymi iTunes. Zauważysz, że nasz kontroler jest bardzo „cienki” (jest to dobra praktyka kodowania). Wszystkie nasze logiczne i trwałe dane znajdują się w naszym serwisie, a nie w naszym kontrolerze.
2) Usługa
Być może największą rzeczą, o której należy wiedzieć podczas tworzenia Usługi, jest to, że jest ona tworzona za pomocą słowa kluczowego „new”. Dla ciebie guru JavaScript powinien dać ci dużą wskazówkę dotyczącą natury kodu. Dla tych z ograniczonym doświadczeniem w JavaScript lub dla tych, którzy nie są zbyt dobrze zaznajomieni z tym, co faktycznie robi „nowe” słowo kluczowe, przejrzyjmy niektóre podstawy JavaScript, które ostatecznie pomogą nam zrozumieć naturę Usługi.
Aby naprawdę zobaczyć zmiany, które następują po wywołaniu funkcji słowem kluczowym „new”, utwórzmy funkcję i wywołaj ją słowem kluczowym „new”, a następnie pokażmy, co robi tłumacz, gdy zobaczy słowo kluczowe „new”. Oba wyniki końcowe będą takie same.
Najpierw stwórzmy naszego Konstruktora.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Jest to typowa funkcja konstruktora JavaScript. Teraz za każdym razem, gdy wywołujemy funkcję Osoba za pomocą słowa kluczowego „new”, „to” zostanie powiązane z nowo utworzonym obiektem.
Dodajmy teraz metodę do prototypu naszej Osoby, aby była dostępna w każdej instancji naszej „klasy” Osoby.
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
Teraz, ponieważ umieszczamy funkcję sayName na prototypie, każda instancja Person będzie mogła wywołać funkcję sayName, aby zaalarmować nazwę tej instancji.
Teraz, gdy mamy prototyp konstruktora Person i funkcję sayName na jego prototypie, utwórzmy instancję Person, a następnie wywołaj funkcję sayName.
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
Cały kod do tworzenia konstruktora Person, dodawania funkcji do jego prototypu, tworzenia instancji Person, a następnie wywoływania funkcji na prototypie wygląda następująco.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
Teraz spójrzmy na to, co się właściwie dzieje, gdy używasz słowa kluczowego „new” w JavaScript. Pierwszą rzeczą, którą powinieneś zauważyć, jest to, że po użyciu „new” w naszym przykładzie jesteśmy w stanie wywołać metodę (sayName) na „tyler” tak, jakby to był obiekt - to dlatego, że tak jest. Po pierwsze wiemy, że nasz konstruktor Person zwraca obiekt, bez względu na to, czy widzimy to w kodzie, czy nie. Po drugie, wiemy, że ponieważ nasza funkcja sayName znajduje się na prototypie, a nie bezpośrednio na instancji Person, obiekt, który zwraca funkcja Person, musi delegować do swojego prototypu podczas nieudanych wyszukiwań. Mówiąc prościej, kiedy wywołujemy tyler.sayName () interpreter mówi „OK, przejrzę właśnie utworzony obiekt„ tyler ”, zlokalizuj funkcję sayName, a następnie wywołaj ją. Chwileczkę, nie widzę tego tutaj - widzę tylko imię i wiek, pozwól mi sprawdzić prototyp. Tak, wygląda na to, że jest na prototypie, nazwijmy to ”.
Poniżej znajduje się kod wyjaśniający, co tak naprawdę robi „nowe” słowo kluczowe w JavaScript. Jest to w zasadzie przykład kodu powyższego akapitu. Umieściłem „widok tłumacza” lub sposób, w jaki tłumacz widzi kod w notatkach.
var Person = function(name, age){
//The below line creates an object(obj) that will delegate to the person’s prototype on failed lookups.
//var obj = Object.create(Person.prototype);
//The line directly below this sets ‘this’ to the newly created object
//this = obj;
this.name = name;
this.age = age;
//return this;
}
Teraz, mając wiedzę na temat tego, co tak naprawdę robi „nowe” słowo kluczowe w JavaScript, tworzenie Usługi w AngularJS powinno być łatwiejsze do zrozumienia.
Najważniejszą rzeczą do zrozumienia podczas tworzenia Usługi jest świadomość, że Usługi są tworzone za pomocą słowa kluczowego „new”. Łącząc tę wiedzę z naszymi powyższymi przykładami, powinieneś teraz wiedzieć, że będziesz przypisywać swoje właściwości i metody bezpośrednio do „tego”, który następnie zostanie zwrócony z samej Usługi. Spójrzmy na to w akcji.
W przeciwieństwie do tego, co pierwotnie zrobiliśmy z przykładem Factory, nie musimy tworzyć obiektu, a następnie zwracać go, ponieważ, jak wspomniano wiele razy wcześniej, użyliśmy słowa kluczowego „new”, aby interpreter utworzył ten obiekt, zlecając mu to prototyp, a następnie zwróć go nam bez konieczności wykonywania pracy.
Po pierwsze, stwórzmy naszą funkcję „prywatną” i pomocniczą. Powinno to wyglądać bardzo znajomo, ponieważ zrobiliśmy dokładnie to samo z naszą fabryką. Nie wyjaśnię, co robi tutaj każda linia, ponieważ zrobiłem to w przykładzie fabrycznym. Jeśli jesteś zdezorientowany, przeczytaj ponownie przykład fabryczny.
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
});
Teraz dołączymy wszystkie nasze metody, które będą dostępne w naszym kontrolerze do „tego”.
app.service('myService', function($http, $q){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.setArtist = function(artist){
_artist = artist;
}
this.getArtist = function(){
return _artist;
}
this.callItunes = function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
}
});
Teraz, podobnie jak w naszej fabryce, setArtist, getArtist i callItunes będą dostępne w dowolnym kontrolerze, do którego przekazujemy myService. Oto kontroler myService (który jest prawie dokładnie taki sam jak nasz kontroler fabryczny).
app.controller('myServiceCtrl', function($scope, myService){
$scope.data = {};
$scope.updateArtist = function(){
myService.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myService.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
});
Jak wspomniałem wcześniej, kiedy naprawdę zrozumiesz, co robi „nowość”, usługi są prawie identyczne z fabrykami w AngularJS.
3) Dostawca
Najważniejszą rzeczą, o której należy pamiętać, jest to, że są to jedyne usługi, które można przekazać do części app.config aplikacji. Ma to ogromne znaczenie, jeśli musisz zmienić pewną część obiektu usługi, zanim będzie on dostępny wszędzie w aplikacji. Chociaż są bardzo podobne do usług / fabryk, istnieje kilka różnic, które omówimy.
Najpierw skonfigurowaliśmy naszego dostawcę w podobny sposób, jak w przypadku naszego serwisu i fabryki. Poniższe zmienne to nasza funkcja „prywatna” i pomocnicza.
app.provider('myProvider', function(){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
//Going to set this property on the config function below.
this.thingFromConfig = ‘’;
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
}
* Ponownie, jeśli jakakolwiek część powyższego kodu jest myląca, sprawdź sekcję Fabryka, w której wyjaśniam, co to wszystko robi, zawiera więcej szczegółów.
Możesz myśleć o Dostawcach jako o trzech sekcjach. Pierwsza sekcja to „prywatne” zmienne / funkcje, które zostaną zmodyfikowane / ustawione później (pokazane powyżej). Druga sekcja to zmienne / funkcje, które będą dostępne w funkcji app.config i dlatego można je zmienić, zanim będą dostępne nigdzie indziej (pokazano również powyżej). Należy zauważyć, że zmienne te muszą być dołączone do słowa kluczowego „this”. W naszym przykładzie w app.config będzie można zmienić tylko „thingFromConfig”. Trzecia sekcja (pokazana poniżej) to wszystkie zmienne / funkcje, które będą dostępne w twoim kontrolerze po przekazaniu usługi „myProvider” do tego konkretnego kontrolera.
Podczas tworzenia usługi z Dostawcą jedynymi właściwościami / metodami, które będą dostępne w twoim kontrolerze, są te właściwości / metody, które są zwracane z funkcji $ get (). Poniższy kod nakłada $ get na „this” (co, jak wiemy, w końcu zostanie zwrócone z tej funkcji). Teraz ta funkcja $ get zwraca wszystkie metody / właściwości, które chcemy być dostępne w kontrolerze. Oto przykład kodu.
this.$get = function($http, $q){
return {
callItunes: function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
},
setArtist: function(artist){
_artist = artist;
},
getArtist: function(){
return _artist;
},
thingOnConfig: this.thingFromConfig
}
}
Teraz pełny kod dostawcy wygląda następująco
app.provider('myProvider', function(){
var baseUrl = 'https://itunes.apple.com/search?term=';
var _artist = '';
var _finalUrl = '';
//Going to set this property on the config function below
this.thingFromConfig = '';
var makeUrl = function(){
_artist = _artist.split(' ').join('+');
_finalUrl = baseUrl + _artist + '&callback=JSON_CALLBACK'
return _finalUrl;
}
this.$get = function($http, $q){
return {
callItunes: function(){
makeUrl();
var deferred = $q.defer();
$http({
method: 'JSONP',
url: _finalUrl
}).success(function(data){
deferred.resolve(data);
}).error(function(){
deferred.reject('There was an error')
})
return deferred.promise;
},
setArtist: function(artist){
_artist = artist;
},
getArtist: function(){
return _artist;
},
thingOnConfig: this.thingFromConfig
}
}
});
Teraz, podobnie jak w naszej fabryce i serwisie, setArtist, getArtist i callItunes będą dostępne w dowolnym kontrolerze, do którego przekazujemy myProvider. Oto kontroler myProvider (który jest prawie dokładnie taki sam jak nasz kontroler fabryczny / serwisowy).
app.controller('myProviderCtrl', function($scope, myProvider){
$scope.data = {};
$scope.updateArtist = function(){
myProvider.setArtist($scope.data.artist);
};
$scope.submitArtist = function(){
myProvider.callItunes()
.then(function(data){
$scope.data.artistData = data;
}, function(data){
alert(data);
})
}
$scope.data.thingFromConfig = myProvider.thingOnConfig;
});
Jak wspomniano wcześniej, celem tworzenia usługi za pomocą dostawcy jest możliwość zmiany niektórych zmiennych za pomocą funkcji app.config, zanim obiekt końcowy zostanie przekazany do reszty aplikacji. Zobaczmy przykład tego.
app.config(function(myProviderProvider){
//Providers are the only service you can pass into app.config
myProviderProvider.thingFromConfig = 'This sentence was set in app.config. Providers are the only service that can be passed into config. Check out the code to see how it works';
});
Teraz możesz zobaczyć, jak „thingFromConfig” jest jak pusty ciąg u naszego dostawcy, ale kiedy to pojawi się w DOM, będzie to „To zdanie zostało ustawione…”.
Wszystkie usługi są singletonami ; są one tworzone raz na aplikację. Mogą być dowolnego typu , bez względu na to, czy jest to prymityw, literał obiektu, funkcja, a nawet instancja typu niestandardowego.
value
, factory
, service
, constant
, I provider
metody są wszyscy dostawcy. Uczą wtryskiwacza, jak tworzyć instancję Usług.
Najbardziej szczegółowym, ale także najbardziej kompleksowym jest przepis na dostawcę. Te pozostałe cztery rodzaje przepis - Wartość, fabryka, serwis i stałe - są po prostu cukier syntaktyczny na szczycie receptury dostawcy .
Z przepisu Provider należy korzystać tylko wtedy, gdy chcesz udostępnić interfejs API dla konfiguracji obejmującej całą aplikację, którą należy wykonać przed uruchomieniem aplikacji. Jest to zwykle interesujące tylko w przypadku usług wielokrotnego użytku, których zachowanie może wymagać nieco różnić w zależności od aplikacji.
decorator
.Zrozumienie fabryki, serwisu i dostawcy AngularJS
Wszystkie z nich służą do udostępniania obiektów singletonowych wielokrotnego użytku. Pomaga udostępniać kod wielokrotnego użytku w aplikacji / różnych komponentach / modułach.
Z serwisu / fabryki dokumentów :
- Instancja lazurowa - Angular tworzy instancję usługi / fabryki tylko wtedy, gdy zależy od niej składnik aplikacji.
- Singletony - każdy komponent zależny od usługi otrzymuje odniesienie do pojedynczego wystąpienia wygenerowanego przez fabrykę usług.
Fabryka to funkcja, w której można manipulować / dodawać logikę przed utworzeniem obiektu, a następnie nowo utworzony obiekt zostaje zwrócony.
app.factory('MyFactory', function() {
var serviceObj = {};
//creating an object with methods/functions or variables
serviceObj.myFunction = function() {
//TO DO:
};
//return that object
return serviceObj;
});
Stosowanie
Może to być tylko zbiór funkcji takich jak klasa. Dlatego może być tworzony w różnych kontrolerach, gdy wstrzykujesz go do funkcji kontrolera / fabryki / dyrektywy. Jest on tworzony tylko raz na aplikację.
Po prostu patrząc na usługi pomyśl o prototypie macierzy. Usługa to funkcja, która tworzy nowy obiekt za pomocą słowa kluczowego „new”. Możesz dodać właściwości i funkcje do obiektu usługi za pomocą this
słowa kluczowego. W przeciwieństwie do fabryki nic nie zwraca (zwraca obiekt zawierający metody / właściwości).
app.service('MyService', function() {
//directly binding events to this context
this.myServiceFunction = function() {
//TO DO:
};
});
Stosowanie
Użyj go, gdy chcesz udostępnić pojedynczy obiekt w aplikacji. Na przykład uwierzytelnione dane użytkownika, udostępniane metody / dane, funkcje narzędziowe itp.
Do utworzenia konfigurowalnego obiektu usługi służy dostawca. Możesz skonfigurować ustawienia usługi za pomocą funkcji konfiguracji. Zwraca wartość za pomocą $get()
funkcji. $get
Funkcja zostanie wykonana na etapie wykonywania w kątowe.
app.provider('configurableService', function() {
var name = '';
//this method can be be available at configuration time inside app.config.
this.setName = function(newName) {
name = newName;
};
this.$get = function() {
var getName = function() {
return name;
};
return {
getName: getName //exposed object to where it gets injected.
};
};
});
Stosowanie
Kiedy musisz udostępnić konfigurację modułową dla obiektu usługi przed udostępnieniem go, np. załóżmy, że chcemy ustawić API URL na podstawie danego środowiska podobnego dev
, stage
lubprod
UWAGA
Tylko dostawca będzie dostępny w fazie konfiguracji kątowej, podczas gdy serwis i fabryka nie.
Mam nadzieję, że to wyjaśniło twoje zrozumienie dotyczące fabryki, serwisu i dostawcy .
only when you want to expose an API for application-wide configuration that must be made before the application starts. This is usually interesting only for reusable services whose behavior might need to vary slightly between applications
, więc nie brzmi to możliwe, prawda?
Dla mnie objawienie pojawiło się, gdy zdałem sobie sprawę, że wszystkie działają w ten sam sposób: uruchamiając coś raz , przechowując otrzymaną wartość, a następnie odkrztuszając tę samą przechowywaną wartość, do której odwołuje się poprzez wstrzyknięcie zależności .
Powiedzmy, że mamy:
app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);
Różnica między tymi trzema polega na tym, że:
a
Zapisana wartość pochodzi z działania fn
.b
Zapisana wartość pochodzi z new
ing fn
.c
Zapisana wartość pochodzi z pierwszego pobrania instancji przez new
ing fn
, a następnie uruchomienia $get
metody instancji.Co oznacza, że wewnątrz AngularJS znajduje się coś w rodzaju obiektu pamięci podręcznej, którego wartość każdego zastrzyku jest przypisywana tylko raz, gdy zostały wstrzyknięte po raz pierwszy i gdzie:
cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()
Dlatego używamy this
w usługach i definiujemy this.$get
dostawców.
factory
s. Jedynymi service
powodami są języki takie jak CoffeeScript, TypeScript, ES6 itp., Więc możesz użyć ich składni klas. Potrzebujesz provider
tylko, jeśli moduł jest używany w kilku aplikacjach z różnymi ustawieniami przy użyciu app.config()
. Jeśli twoja usługa jest czystym singletonem lub jest w stanie stworzyć instancje czegoś, zależy tylko od twojej implementacji.
Usługa kontra dostawca vs fabryka:
Staram się to uprościć. Chodzi o podstawową koncepcję JavaScript.
Przede wszystkim porozmawiajmy o usługach w AngularJS!
Co to jest usługa: w AngularJS, usługajest niczym innym jak pojedynczym obiektem JavaScript, który może przechowywać użyteczne metody lub właściwości. Ten obiekt singletonowy jest tworzony na podstawie ngApp (aplikacja Angular) i jest współdzielony przez wszystkie kontrolery w bieżącej aplikacji. Kiedy Angularjs tworzy obiekt usługi, rejestruje ten obiekt usługi pod unikalną nazwą usługi. Dlatego za każdym razem, gdy potrzebujemy wystąpienia usługi, Angular przeszukuje rejestr w poszukiwaniu tej nazwy usługi i zwraca odwołanie do obiektu usługi. Tak, że możemy wywołać metodę, dostęp do właściwości itp. Na obiekcie usługi. Możesz mieć pytanie, czy możesz również umieścić właściwości, metody na obiekcie zakresu kontrolerów! Dlaczego więc potrzebujesz obiektu usługi? Odpowiedź brzmi: usługi są współużytkowane przez wiele kontrolerów. Jeśli umieścisz niektóre właściwości / metody w obiekcie zakresu kontrolera, będzie on dostępny tylko dla bieżącego zakresu.
Jeśli więc istnieją trzy zakresy kontrolerów, niech będą to kontroler A, kontroler B i kontroler C, wszystkie będą współużytkować tę samą instancję usługi.
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
Jak stworzyć usługę?
AngularJS zapewnia różne metody rejestracji usługi. Tutaj skoncentrujemy się na trzech metodach: fabryce (..), serwisie (..), dostawcy (..);
Użyj tego linku jako odniesienia do kodu
Możemy zdefiniować funkcję fabryczną jak poniżej.
factory('serviceName',function fnFactory(){ return serviceInstance;})
AngularJS zapewnia metodę „factory („ serviceName ”, fnFactory)” , która przyjmuje dwa parametry: serviceName i funkcję JavaScript. Angular tworzy instancję usługi, wywołując funkcję fnFactory (), taką jak poniżej.
var serviceInstace = fnFactory();
Przekazana funkcja może zdefiniować obiekt i zwrócić ten obiekt. AngularJS po prostu przechowuje to odwołanie do obiektu do zmiennej, która jest przekazywana jako pierwszy argument. Wszystko, co zostanie zwrócone z fnFactory, będzie powiązane z usługą serviceInstance. Zamiast zwracać obiekt, możemy również zwrócić funkcję, wartości itp. Cokolwiek zwrócimy, będzie dostępne dla instancji usługi.
Przykład:
var app= angular.module('myApp', []);
//creating service using factory method
app.factory('factoryPattern',function(){
var data={
'firstName':'Tom',
'lastName':' Cruise',
greet: function(){
console.log('hello!' + this.firstName + this.lastName);
}
};
//Now all the properties and methods of data object will be available in our service object
return data;
});
service('serviceName',function fnServiceConstructor(){})
To inny sposób, w jaki możemy zarejestrować usługę. Jedyną różnicą jest sposób, w jaki AngularJS próbuje utworzyć instancję obiektu usługi. Tym razem angular używa słowa kluczowego „new” i wywołuje funkcję konstruktora jak poniżej.
var serviceInstance = new fnServiceConstructor();
W funkcji konstruktora możemy użyć słowa kluczowego „this” do dodania właściwości / metod do obiektu usługi. przykład:
//Creating a service using the service method
var app= angular.module('myApp', []);
app.service('servicePattern',function(){
this.firstName ='James';
this.lastName =' Bond';
this.greet = function(){
console.log('My Name is '+ this.firstName + this.lastName);
};
});
Funkcja Provider () to kolejny sposób tworzenia usług. Pozwól nam zainteresować się stworzeniem usługi, która po prostu wyświetli powitanie dla użytkownika. Ale chcemy również zapewnić taką funkcjonalność, aby użytkownik mógł ustawić własne powitanie. Z technicznego punktu widzenia chcemy tworzyć konfigurowalne usługi. Jak możemy to zrobić? Musi istnieć sposób, aby aplikacja mogła przekazać swoje niestandardowe wiadomości powitalne, a Angularjs udostępniłby ją funkcji fabryki / konstruktora, która tworzy instancję naszych usług. W takim przypadku funkcja dostawca () wykonuje zadanie. za pomocą funkcji provider () możemy tworzyć konfigurowalne usługi.
Możemy tworzyć konfigurowalne usługi przy użyciu składni dostawcy, jak podano poniżej.
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
1. Obiekt Provider jest tworzony za pomocą funkcji konstruktora, którą zdefiniowaliśmy w naszej funkcji dostawcy.
var serviceProvider = new serviceProviderConstructor();
2. Funkcja, którą przekazaliśmy w app.config (), zostanie wykonana. Nazywa się to fazą konfiguracji i tutaj mamy szansę na dostosowanie naszej usługi.
configureService(serviceProvider);
3. Wreszcie instancja usługi jest tworzona przez wywołanie metody $ get z serviceProvider.
serviceInstance = serviceProvider.$get()
var app= angular.module('myApp', []);
app.provider('providerPattern',function providerConstructor(){
//this function works as constructor function for provider
this.firstName = 'Arnold ';
this.lastName = ' Schwarzenegger' ;
this.greetMessage = ' Welcome, This is default Greeting Message' ;
//adding some method which we can call in app.config() function
this.setGreetMsg = function(msg){
if(msg){
this.greetMessage = msg ;
}
};
//We can also add a method which can change firstName and lastName
this.$get = function(){
var firstName = this.firstName;
var lastName = this.lastName ;
var greetMessage = this.greetMessage;
var data={
greet: function(){
console.log('hello, ' + firstName + lastName+'! '+ greetMessage);
}
};
return data ;
};
});
app.config(
function(providerPatternProvider){
providerPatternProvider.setGreetMsg(' How do you do ?');
}
);
Podsumowanie:
Fabrycznie użyj funkcji fabryki, która zwraca instancję usługi. serviceInstance = fnFactory ();
Usługa korzysta z funkcji konstruktora, a Angular wywołuje tę funkcję konstruktora, używając słowa kluczowego „new” do utworzenia instancji usługi. serviceInstance = new fnServiceConstructor ();
Dostawca definiuje funkcję dostawcaKonstruktor, ta funkcja dostawcaKonstruktor definiuje funkcję fabryczną $ get . Angular wywołuje $ get () w celu utworzenia obiektu usługi. Składnia dostawcy ma dodatkową zaletę konfigurowania obiektu usługi przed jego utworzeniem. serviceInstance = $ get ();
Jak wskazało tutaj kilka osób, fabryka, dostawca, usługa, a nawet wartość i stała są wersjami tego samego. Możesz podzielić bardziej ogólne provider
na wszystkie z nich. Tak jak:
Oto artykuł z tego obrazu:
Dajesz AngularJS funkcję, AngularJS zbuforuje pamięć podręczną i wstrzykuje wartość zwracaną, gdy zażąda tego fabryka.
Przykład:
app.factory('factory', function() {
var name = '';
// Return value **is** the object that will be injected
return {
name: name;
}
})
Stosowanie:
app.controller('ctrl', function($scope, factory) {
$scope.name = factory.name;
});
Dajesz AngularJS funkcję, AngularJS wywoła new, aby ją utworzyć. Jest to instancja utworzona przez AngularJS, która będzie buforowana i wstrzykiwana, gdy usługa zostanie zażądana. Ponieważ nowy użyto instancji usługi, słowo to jest ważna i odnosi się do instancji.
Przykład:
app.service('service', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.getName = function() {
return name;
}
});
Stosowanie:
app.controller('ctrl', function($scope, service) {
$scope.name = service.getName();
});
Dajesz AngularJS funkcję, a AngularJS wywoła tę $get
funkcję. Jest to wartość zwracana z $get
funkcji, która będzie buforowana i wstrzykiwana, gdy usługa zostanie zażądana.
Dostawcy pozwalają skonfigurować dostawcę, zanim AngularJS $get
wywoła metodę uzyskania wstrzyknięcia.
Przykład:
app.provider('provider', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.$get = function() {
return {
name: name
}
}
})
Zastosowanie (jako wstrzyknięcie w sterowniku)
app.controller('ctrl', function($scope, provider) {
$scope.name = provider.name;
});
Użycie (wcześniej skonfigurowano dostawcę, $get
aby utworzyć plik do wstrzykiwania)
app.config(function(providerProvider) {
providerProvider.setName('John');
});
Zauważyłem coś interesującego podczas zabawy z dostawcami.
Widoczność zastrzyków jest inna dla dostawców niż dla usług i fabryk. Jeśli zadeklarujesz „stałą” AngularJS (na przykład myApp.constant('a', 'Robert');
), możesz wprowadzić ją do usług, fabryk i dostawców.
Ale jeśli zadeklarujesz „wartość” AngularJS (na przykład. myApp.value('b', {name: 'Jones'});
), Możesz wstrzyknąć ją do usług i fabryk, ale NIE do funkcji tworzenia dostawcy. Możesz jednak wprowadzić ją do $get
funkcji zdefiniowanej dla swojego dostawcy. Jest to wspomniane w dokumentacji AngularJS, ale łatwo go przeoczyć. Można go znaleźć na stronie% dostarczyć w sekcjach dotyczących wartości i metod stałych.
<div ng-app="MyAppName">
<div ng-controller="MyCtrl">
<p>from Service: {{servGreet}}</p>
<p>from Provider: {{provGreet}}</p>
</div>
</div>
<script>
var myApp = angular.module('MyAppName', []);
myApp.constant('a', 'Robert');
myApp.value('b', {name: 'Jones'});
myApp.service('greetService', function(a,b) {
this.greeter = 'Hi there, ' + a + ' ' + b.name;
});
myApp.provider('greetProvider', function(a) {
this.firstName = a;
this.$get = function(b) {
this.lastName = b.name;
this.fullName = this.firstName + ' ' + this.lastName;
return this;
};
});
function MyCtrl($scope, greetService, greetProvider) {
$scope.servGreet = greetService.greeter;
$scope.provGreet = greetProvider.fullName;
}
</script>
Jest to bardzo mylące dla początkujących i starałem się to wyjaśnić prostymi słowami
Usługa AngularJS: służy do współdzielenia funkcji narzędziowych z odniesieniem do usługi w kontrolerze. Usługa ma charakter singleton, więc w przypadku jednej usługi w przeglądarce tworzona jest tylko jedna instancja, a na stronie używane jest to samo odwołanie.
W usłudze tworzymy nazwy funkcji jako właściwość dla tego obiektu.
AngularJS Factory: cel Factory jest również taki sam jak Service, ale w tym przypadku tworzymy nowy obiekt i dodajemy funkcje jako właściwości tego obiektu, a na koniec zwracamy ten obiekt.
AngularJS Provider: cel tego jest ponownie taki sam, jednak Provider podaje wynik funkcji $ get.
Definiowanie i korzystanie z usługi, fabryki i dostawcy wyjaśniono na stronie http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider
Dla mnie najlepszym i najprostszym sposobem zrozumienia różnicy jest:
var service, factory;
service = factory = function(injection) {}
Jak AngularJS tworzy poszczególne komponenty (uproszczone):
// service
var angularService = new service(injection);
// factory
var angularFactory = factory(injection);
Tak więc dla usługi komponent AngularJS staje się instancją obiektu klasy reprezentowaną przez funkcję deklaracji usługi. W przypadku fabryki jest to wynik zwracany z funkcji deklaracji fabrycznej. Fabryka może zachowywać się tak samo jak usługa:
var factoryAsService = function(injection) {
return new function(injection) {
// Service content
}
}
Najprostszy sposób myślenia jest następujący:
Fabryczny przykład „klasy” znajduje się w komentarzach, a także różnice między dostawcami.
new MyService()
czy coś :)
Moje wyjaśnienie w tej sprawie:
Zasadniczo wszystkie wymienione typy (usługa, fabryka, dostawca itp.) Po prostu tworzą i konfigurują zmienne globalne (które są oczywiście globalne dla całej aplikacji), podobnie jak staromodne zmienne globalne.
Chociaż zmienne globalne nie są zalecane, prawdziwym zastosowaniem tych zmiennych globalnych jest zapewnienie wstrzyknięcia zależności , poprzez przekazanie zmiennej do odpowiedniego kontrolera.
Istnieje wiele poziomów komplikacji w tworzeniu wartości dla „zmiennych globalnych”:
app.config
.
app.config
pliku, a ta funkcja $ .get zachowuje się tak jak fabryka powyżej, ponieważ jego wartość zwracana jest używana do inicjalizacji zmiennych „globalnych”. Moje zrozumienie jest bardzo proste poniżej.
Fabryka: po prostu tworzysz obiekt w fabryce i oddajesz go.
Usługa:
Masz tylko standardową funkcję, która używa tego słowa kluczowego do zdefiniowania funkcji.
Dostawca:
Istnieje $get
obiekt, który zdefiniujesz i można go użyć do uzyskania obiektu, który zwraca dane.
Podsumowanie z dokumentów Angular :
Najlepsze odpowiedzi z SO:
https://stackoverflow.com/a/26924234/165673 (<- DOBRY)
https://stackoverflow.com/a/27263882/165673
https://stackoverflow.com/a/16566144/165673
Wszystkie dobre odpowiedzi już. Chciałbym dodać jeszcze kilka punktów w serwisie i fabryce . Wraz z różnicą między serwisem / fabryką. Można też zadawać pytania:
Zacznijmy od różnicy między usługą a fabryką:
Oba są singletonami : ilekroć Angular po raz pierwszy znajdzie je jako zależność, tworzy pojedyncze wystąpienie usługi / fabryki. Po utworzeniu instancji ta sama instancja jest używana na zawsze.
Może być użyty do modelowania obiektu z zachowaniem : Oba mogą mieć metody, wewnętrzne zmienne stanu i tak dalej. Chociaż sposób pisania tego kodu będzie inny.
Usługi:
Usługa jest funkcją konstruktora, a Angular utworzy ją, wywołując new yourServiceName()
. Oznacza to kilka rzeczy.
this
.new yourServiceName(
), otrzyma this
obiekt ze wszystkimi właściwościami, które na niego umieścisz.Przykładowy przykład:
angular.service('MyService', function() {
this.aServiceVariable = "Ved Prakash"
this.aServiceMethod = function() {
return //code
};
});
Gdy Angular wstrzykuje tę
MyService
usługę do kontrolera, który jest od niej zależny, ten kontroler otrzyma funkcjęMyService
, na której może wywoływać funkcje, np. MyService.aServiceMethod ().
Uważaj nathis
:
Ponieważ skonstruowana usługa jest obiektem, znajdujące się w niej metody mogą się do tego odwoływać, gdy są wywoływane:
angular.service('ScoreKeeper', function($http) {
this.score = 0;
this.getScore = function() {
return this.score;
};
this.setScore = function(newScore) {
this.score = newScore;
};
this.addOne = function() {
this.score++;
};
});
Możesz mieć ochotę sprawdzić ScoreKeeper.setScore
w łańcuchu obietnic, na przykład, jeśli zainicjowałeś wynik, chwytając go z serwera: $http.get('/score').then(ScoreKeeper.setScore).
Problem polega na tym, że ScoreKeeper.setScore
zostanie wywołany z this
powiązaniem z, null
a otrzymasz błędy. Byłby lepszy sposób $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper))
. Niezależnie od tego, czy zdecydujesz się użyć tego w swoich metodach serwisowych, czy nie, bądź ostrożny, jak je nazywasz.
Zwracanie wartości zService
:
Ze względu na działanie konstruktorów JavaScript, jeśli zwrócisz wartość złożoną (i.e., an Object)
z constructor
funkcji, program wywołujący otrzyma ten obiekt zamiast tego wystąpienia.
Oznacza to, że możesz w zasadzie skopiować i wkleić przykład fabryczny od dołu, zastąpić factory
go service
, a to zadziała:
angular.service('MyService', function($http) {
var api = {};
api.aServiceMethod= function() {
return $http.get('/users');
};
return api;
});
Więc kiedy Angular konstruuje twoją usługę za pomocą nowej MyService (), otrzyma ten obiekt interfejsu API zamiast instancji MyService.
Jest to zachowanie dla dowolnych złożonych wartości (obiektów, funkcji), ale nie dla typów pierwotnych.
Fabryki:
Fabryka jest zwykłą starą funkcją, która zwraca wartość. Wartość zwracana jest wprowadzana do rzeczy zależnych od fabryki. Typowym wzorcem fabrycznym w Angular jest zwracanie obiektu z funkcjami jako właściwości, jak poniżej:
angular.factory('MyFactory', function($http) {
var api = {};
api.aFactoryMethod= function() {
return $http.get('/users');
};
return api;
});
Wprowadzona wartość zależności fabrycznej jest wartością zwracaną przez fabrykę i nie musi to być obiekt. To może być funkcja
Odpowiedzi na pytania powyżej 1 i 2:
Przeważnie trzymaj się fabryk do wszystkiego. Ich zachowanie jest łatwiejsze do zrozumienia. Nie ma wyboru, czy zwrócić wartość, czy nie, a ponadto, jeśli zrobisz coś złego, nie zostaną wprowadzone żadne błędy.
Nadal nazywam je „usługami”, kiedy mówię o wprowadzaniu ich jako zależności.
Zachowanie serwisowe / fabryczne jest bardzo podobne, a niektórzy powiedzą, że jedno z nich jest w porządku. To trochę prawda, ale łatwiej mi postępować zgodnie z radą przewodnika po stylu Johna Papy i trzymać się fabryk. **
Dodatkowym wyjaśnieniem jest to, że fabryki mogą tworzyć funkcje / operacje podstawowe, podczas gdy usługi nie. Sprawdź to jsFiddle oparte na Epokk's: http://jsfiddle.net/skeller88/PxdSP/1351/ .
Fabryka zwraca funkcję, którą można wywołać:
myApp.factory('helloWorldFromFactory', function() {
return function() {
return "Hello, World!";
};
});
Fabryka może również zwrócić obiekt za pomocą metody, którą można wywołać:
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
Usługa zwraca obiekt za pomocą metody, którą można wywołać:
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
Aby uzyskać więcej informacji, zobacz post, który napisałem o różnicy: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/
Są już dobre odpowiedzi, ale chcę się tylko z tym podzielić.
Po pierwsze: dostawca to sposób / przepis na stworzenieservice
(obiektu singleton), który powinien być wstrzykiwany przez $ injector (jak AngulaJS podchodzi do wzoru IoC).
I wartość, fabryka, obsługa i stała (4 sposoby) - cukier składniowy w stosunku do sposobu dostawcy / recepty.
Jest Service vs Factory
część została pokryta:
https://www.youtube.com/watch?v=BLzNCkPn3ao
Usługa polega new
właściwie na słowach kluczowych, które, jak wiemy, obejmują 4 rzeczy:
prototype
obiektemcontext
zthis
this
A fabryka jest o fabryczne Pattern - zawiera funkcje, które zwracają obiekty tak Serwisu.
I ten prosty / krótki film: obejmuje również dostawcę : https://www.youtube.com/watch?v=HvTZbQ_hUZY (tam widać, jak przechodzą od fabryki do dostawcy)
Przepis dostawcy jest używany głównie w konfiguracji aplikacji, zanim aplikacja zostanie w pełni uruchomiona / zainicjowana.
Po przeczytaniu wszystkich tych postów stworzyło to dla mnie więcej zamieszania .. Ale nadal wszystkie wartościowe informacje .. w końcu znalazłem poniższą tabelę, która poda informacje z prostym porównaniem
A dla początkującego rozumiem: - To może nie poprawić przypadku użycia, ale na wysokim poziomie jest to przypadek użycia tych trzech.
angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})
W przypadku podstawowych scenariuszy fabryka i obsługa zachowują się tak samo.
Oto kod brojlerów, który wymyśliłem jako szablon kodu dla fabryki obiektów w AngularjS. Jako przykład zilustrowałem Car / CarFactory. Tworzy prosty kod implementacyjny w kontrolerze.
<script>
angular.module('app', [])
.factory('CarFactory', function() {
/**
* BroilerPlate Object Instance Factory Definition / Example
*/
this.Car = function() {
// initialize instance properties
angular.extend(this, {
color : null,
numberOfDoors : null,
hasFancyRadio : null,
hasLeatherSeats : null
});
// generic setter (with optional default value)
this.set = function(key, value, defaultValue, allowUndefined) {
// by default,
if (typeof allowUndefined === 'undefined') {
// we don't allow setter to accept "undefined" as a value
allowUndefined = false;
}
// if we do not allow undefined values, and..
if (!allowUndefined) {
// if an undefined value was passed in
if (value === undefined) {
// and a default value was specified
if (defaultValue !== undefined) {
// use the specified default value
value = defaultValue;
} else {
// otherwise use the class.prototype.defaults value
value = this.defaults[key];
} // end if/else
} // end if
} // end if
// update
this[key] = value;
// return reference to this object (fluent)
return this;
}; // end this.set()
}; // end this.Car class definition
// instance properties default values
this.Car.prototype.defaults = {
color: 'yellow',
numberOfDoors: 2,
hasLeatherSeats: null,
hasFancyRadio: false
};
// instance factory method / constructor
this.Car.prototype.instance = function(params) {
return new
this.constructor()
.set('color', params.color)
.set('numberOfDoors', params.numberOfDoors)
.set('hasFancyRadio', params.hasFancyRadio)
.set('hasLeatherSeats', params.hasLeatherSeats)
;
};
return new this.Car();
}) // end Factory Definition
.controller('testCtrl', function($scope, CarFactory) {
window.testCtrl = $scope;
// first car, is red, uses class default for:
// numberOfDoors, and hasLeatherSeats
$scope.car1 = CarFactory
.instance({
color: 'red'
})
;
// second car, is blue, has 3 doors,
// uses class default for hasLeatherSeats
$scope.car2 = CarFactory
.instance({
color: 'blue',
numberOfDoors: 3
})
;
// third car, has 4 doors, uses class default for
// color and hasLeatherSeats
$scope.car3 = CarFactory
.instance({
numberOfDoors: 4
})
;
// sets an undefined variable for 'hasFancyRadio',
// explicitly defines "true" as default when value is undefined
$scope.hasFancyRadio = undefined;
$scope.car3.set('hasFancyRadio', $scope.hasFancyRadio, true);
// fourth car, purple, 4 doors,
// uses class default for hasLeatherSeats
$scope.car4 = CarFactory
.instance({
color: 'purple',
numberOfDoors: 4
});
// and then explicitly sets hasLeatherSeats to undefined
$scope.hasLeatherSeats = undefined;
$scope.car4.set('hasLeatherSeats', $scope.hasLeatherSeats, undefined, true);
// in console, type window.testCtrl to see the resulting objects
});
</script>
Oto prostszy przykład. Korzystam z kilku bibliotek stron trzecich, które oczekują obiektu „Pozycja” pokazującego szerokość i długość geograficzną, ale za pomocą różnych właściwości obiektu. Nie chciałem zhakować kodu dostawcy, więc dostosowałem przekazywane przeze mnie obiekty „Pozycjonowanie”.
angular.module('app')
.factory('PositionFactory', function() {
/**
* BroilerPlate Object Instance Factory Definition / Example
*/
this.Position = function() {
// initialize instance properties
// (multiple properties to satisfy multiple external interface contracts)
angular.extend(this, {
lat : null,
lon : null,
latitude : null,
longitude : null,
coords: {
latitude: null,
longitude: null
}
});
this.setLatitude = function(latitude) {
this.latitude = latitude;
this.lat = latitude;
this.coords.latitude = latitude;
return this;
};
this.setLongitude = function(longitude) {
this.longitude = longitude;
this.lon = longitude;
this.coords.longitude = longitude;
return this;
};
}; // end class definition
// instance factory method / constructor
this.Position.prototype.instance = function(params) {
return new
this.constructor()
.setLatitude(params.latitude)
.setLongitude(params.longitude)
;
};
return new this.Position();
}) // end Factory Definition
.controller('testCtrl', function($scope, PositionFactory) {
$scope.position1 = PositionFactory.instance({latitude: 39, longitude: 42.3123});
$scope.position2 = PositionFactory.instance({latitude: 39, longitude: 42.3333});
}) // end controller
;
Wykorzystując jako odniesienie tę stronę i dokumentację (która wydaje się znacznie ulepszona od czasu ostatniego spojrzenia), stworzyłem następujące prawdziwe (-ish) światowe demo, które wykorzystuje 4 z 5 smaków dostawcy; Wartość, stała, fabryczna i pełna oferta dostawcy.
HTML:
<div ng-controller="mainCtrl as main">
<h1>{{main.title}}*</h1>
<h2>{{main.strapline}}</h2>
<p>Earn {{main.earn}} per click</p>
<p>You've earned {{main.earned}} by clicking!</p>
<button ng-click="main.handleClick()">Click me to earn</button>
<small>* Not actual money</small>
</div>
app
var app = angular.module('angularProviders', []);
// A CONSTANT is not going to change
app.constant('range', 100);
// A VALUE could change, but probably / typically doesn't
app.value('title', 'Earn money by clicking');
app.value('strapline', 'Adventures in ng Providers');
// A simple FACTORY allows us to compute a value @ runtime.
// Furthermore, it can have other dependencies injected into it such
// as our range constant.
app.factory('random', function randomFactory(range) {
// Get a random number within the range defined in our CONSTANT
return Math.random() * range;
});
// A PROVIDER, must return a custom type which implements the functionality
// provided by our service (see what I did there?).
// Here we define the constructor for the custom type the PROVIDER below will
// instantiate and return.
var Money = function(locale) {
// Depending on locale string set during config phase, we'll
// use different symbols and positioning for any values we
// need to display as currency
this.settings = {
uk: {
front: true,
currency: '£',
thousand: ',',
decimal: '.'
},
eu: {
front: false,
currency: '€',
thousand: '.',
decimal: ','
}
};
this.locale = locale;
};
// Return a monetary value with currency symbol and placement, and decimal
// and thousand delimiters according to the locale set in the config phase.
Money.prototype.convertValue = function(value) {
var settings = this.settings[this.locale],
decimalIndex, converted;
converted = this.addThousandSeparator(value.toFixed(2), settings.thousand);
decimalIndex = converted.length - 3;
converted = converted.substr(0, decimalIndex) +
settings.decimal +
converted.substr(decimalIndex + 1);
converted = settings.front ?
settings.currency + converted :
converted + settings.currency;
return converted;
};
// Add supplied thousand separator to supplied value
Money.prototype.addThousandSeparator = function(value, symbol) {
return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, symbol);
};
// PROVIDER is the core recipe type - VALUE, CONSTANT, SERVICE & FACTORY
// are all effectively syntactic sugar built on top of the PROVIDER construct
// One of the advantages of the PROVIDER is that we can configure it before the
// application starts (see config below).
app.provider('money', function MoneyProvider() {
var locale;
// Function called by the config to set up the provider
this.setLocale = function(value) {
locale = value;
};
// All providers need to implement a $get method which returns
// an instance of the custom class which constitutes the service
this.$get = function moneyFactory() {
return new Money(locale);
};
});
// We can configure a PROVIDER on application initialisation.
app.config(['moneyProvider', function(moneyProvider) {
moneyProvider.setLocale('uk');
//moneyProvider.setLocale('eu');
}]);
// The ubiquitous controller
app.controller('mainCtrl', function($scope, title, strapline, random, money) {
// Plain old VALUE(s)
this.title = title;
this.strapline = strapline;
this.count = 0;
// Compute values using our money provider
this.earn = money.convertValue(random); // random is computed @ runtime
this.earned = money.convertValue(0);
this.handleClick = function() {
this.count ++;
this.earned = money.convertValue(random * this.count);
};
});
Działające demo .
Ta odpowiedź dotyczy tematu / pytania
LUB
w zasadzie to, co się dzieje
Kiedy tworzysz zestaw factory()
it function
podany w drugim argumencie dostawcy $get
i zwraca go ( provider(name, {$get:factoryFn })
), wszystko, co otrzymujesz, provider
to brak właściwości / metody innej niż$get
ta provider
(oznacza, że nie możesz tego skonfigurować)
Kod źródłowy fabryki
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
};
Dokonując service()
zwrotu, użytkownik udostępnia fabrykę (), function
która wstrzykuje constructor
(zwraca instancję konstruktora podaną w usłudze) i zwraca ją
Kod źródłowy usługi
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
};
Zasadniczo w obu przypadkach ostatecznie otrzymasz dostawcę $ ustawioną na podaną funkcję, ale możesz podać coś więcej niż $ get, jak pierwotnie możesz podać w dostawca () dla bloku konfiguracji
Znam wiele doskonałych odpowiedzi, ale muszę podzielić się swoim doświadczeniem w korzystaniu z
1. service
w większości przypadków domyślnie
2. factory
użytych do stworzenia usługi dla tej konkretnej instancji
// factory.js ////////////////////////////
(function() {
'use strict';
angular
.module('myApp.services')
.factory('xFactory', xFactoryImp);
xFactoryImp.$inject = ['$http'];
function xFactoryImp($http) {
var fac = function (params) {
this._params = params; // used for query params
};
fac.prototype.nextPage = function () {
var url = "/_prc";
$http.get(url, {params: this._params}).success(function(data){ ...
}
return fac;
}
})();
// service.js //////////////////////////
(function() {
'use strict';
angular
.module('myApp.services')
.service('xService', xServiceImp);
xServiceImp.$inject = ['$http'];
function xServiceImp($http) {
this._params = {'model': 'account','mode': 'list'};
this.nextPage = function () {
var url = "/_prc";
$http.get(url, {params: this._params}).success(function(data){ ...
}
}
})();
i używając:
controller: ['xFactory', 'xService', function(xFactory, xService){
// books = new instance of xFactory for query 'book' model
var books = new xFactory({'model': 'book', 'mode': 'list'});
// accounts = new instance of xFactory for query 'accounts' model
var accounts = new xFactory({'model': 'account', 'mode': 'list'});
// accounts2 = accounts variable
var accounts2 = xService;
...
Trochę późno na imprezę. Ale pomyślałem, że jest to bardziej pomocne dla tych, którzy chcieliby się dowiedzieć (lub mieć jasność) na temat opracowywania niestandardowych usług Angular JS przy użyciu metod produkcji, usług i dostawców.
Natknąłem się na ten film, który jasno wyjaśnia metody produkcji, usług i dostawcy w celu opracowania usług niestandardowych AngularJS:
https://www.youtube.com/watch?v=oUXku28ex-M
Kod źródłowy: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service
Kod zamieszczony tutaj jest kopiowany bezpośrednio z powyższego źródła, z korzyścią dla czytelników.
Kod niestandardowej usługi „fabrycznej” jest następujący (która dotyczy zarówno wersji synchronicznej, jak i asynchronicznej wraz z wywoływaniem usługi http):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcFactory',
function($scope, calcFactory) {
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function() {
//$scope.sum = calcFactory.getSum($scope.a, $scope.b); //synchronous
calcFactory.getSum($scope.a, $scope.b, function(r) { //aynchronous
$scope.sum = r;
});
};
}
]);
app.factory('calcFactory', ['$http', '$log',
function($http, $log) {
$log.log("instantiating calcFactory..");
var oCalcService = {};
//oCalcService.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//oCalcService.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
oCalcService.getSum = function(a, b, cb) { //using http service
$http({
url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp) {
$log.log(resp.data);
cb(resp.data);
}, function(resp) {
$log.error("ERROR occurred");
});
};
return oCalcService;
}
]);
Kod metodyki „usługi” dla usług niestandardowych (jest podobny do „fabryki”, ale różni się od punktu widzenia składni):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function(){
//$scope.sum = calcService.getSum($scope.a, $scope.b);
calcService.getSum($scope.a, $scope.b, function(r){
$scope.sum = r;
});
};
}]);
app.service('calcService', ['$http', '$log', function($http, $log){
$log.log("instantiating calcService..");
//this.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//this.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
this.getSum = function(a, b, cb){
$http({
url: 'http://localhost:4467/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp){
$log.log(resp.data);
cb(resp.data);
},function(resp){
$log.error("ERROR occurred");
});
};
}]);
Kod metodyki „dostawcy” dla usług niestandardowych (jest to konieczne, jeśli chcesz opracować usługę, którą można skonfigurować):
var app = angular.module("app", []);
app.controller('emp', ['$scope', 'calcService', function($scope, calcService){
$scope.a = 10;
$scope.b = 20;
$scope.doSum = function(){
//$scope.sum = calcService.getSum($scope.a, $scope.b);
calcService.getSum($scope.a, $scope.b, function(r){
$scope.sum = r;
});
};
}]);
app.provider('calcService', function(){
var baseUrl = '';
this.config = function(url){
baseUrl = url;
};
this.$get = ['$log', '$http', function($log, $http){
$log.log("instantiating calcService...")
var oCalcService = {};
//oCalcService.getSum = function(a,b){
// return parseInt(a) + parseInt(b);
//};
//oCalcService.getSum = function(a, b, cb){
// var s = parseInt(a) + parseInt(b);
// cb(s);
//};
oCalcService.getSum = function(a, b, cb){
$http({
url: baseUrl + '/Sum?a=' + a + '&b=' + b,
method: 'GET'
}).then(function(resp){
$log.log(resp.data);
cb(resp.data);
},function(resp){
$log.error("ERROR occurred");
});
};
return oCalcService;
}];
});
app.config(['calcServiceProvider', function(calcServiceProvider){
calcServiceProvider.config("http://localhost:4467");
}]);
Wreszcie interfejs użytkownika współpracujący z dowolną z powyższych usług:
<html>
<head>
<title></title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js" ></script>
<script type="text/javascript" src="t03.js"></script>
</head>
<body ng-app="app">
<div ng-controller="emp">
<div>
Value of a is {{a}},
but you can change
<input type=text ng-model="a" /> <br>
Value of b is {{b}},
but you can change
<input type=text ng-model="b" /> <br>
</div>
Sum = {{sum}}<br>
<button ng-click="doSum()">Calculate</button>
</div>
</body>
</html>
Aby to wyjaśnić, ze źródła AngularJS można zobaczyć, że usługa wywołuje funkcję fabryczną, która z kolei wywołuje funkcję dostawcy:
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Omówmy trzy sposoby obsługi logiki biznesowej w AngularJS w prosty sposób: ( Zainspirowany kursem Yaakova Coursera AngularJS )
SERWIS :
Składnia:
app.js
var app = angular.module('ServiceExample',[]);
var serviceExampleController =
app.controller('ServiceExampleController', ServiceExampleController);
var serviceExample = app.service('NameOfTheService', NameOfTheService);
ServiceExampleController.$inject = ['NameOfTheService'] //protects from minification of js files
function ServiceExampleController(NameOfTheService){
serviceExampleController = this;
serviceExampleController.data = NameOfTheService.getSomeData();
}
function NameOfTheService(){
nameOfTheService = this;
nameOfTheService.data = "Some Data";
nameOfTheService.getSomeData = function(){
return nameOfTheService.data;
}
}
index.html
<div ng-controller = "ServiceExampleController as serviceExample">
{{serviceExample.data}}
</div>
Funkcje usługi:
FABRYKA
Najpierw spójrzmy na składnię:
app.js :
var app = angular.module('FactoryExample',[]);
var factoryController = app.controller('FactoryController', FactoryController);
var factoryExampleOne = app.factory('NameOfTheFactoryOne', NameOfTheFactoryOne);
var factoryExampleTwo = app.factory('NameOfTheFactoryTwo', NameOfTheFactoryTwo);
//first implementation where it returns a function
function NameOfTheFactoryOne(){
var factory = function(){
return new SomeService();
}
return factory;
}
//second implementation where an object literal would be returned
function NameOfTheFactoryTwo(){
var factory = {
getSomeService : function(){
return new SomeService();
}
};
return factory;
}
Teraz używając dwóch powyższych w kontrolerze:
var factoryOne = NameOfTheFactoryOne() //since it returns a function
factoryOne.someMethod();
var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
factoryTwo.someMethod();
Funkcje fabryki:
.service()
Metoda jest fabryka , która zawsze daje ten sam rodzaj usługi, która jest pojedyncza i bez łatwy sposób skonfigurować jej zachowanie. Ta .service()
metoda jest zwykle używana jako skrót do czegoś, co nie wymaga żadnej konfiguracji.DOSTAWCA
Przyjrzyjmy się najpierw składni:
angular.module('ProviderModule', [])
.controller('ProviderModuleController', ProviderModuleController)
.provider('ServiceProvider', ServiceProvider)
.config(Config); //optional
Config.$inject = ['ServiceProvider'];
function Config(ServiceProvider) {
ServiceProvider.defaults.maxItems = 10; //some default value
}
ProviderModuleController.$inject = ['ServiceProvider'];
function ProviderModuleController(ServiceProvider) {
//some methods
}
function ServiceProvider() {
var provider = this;
provider.defaults = {
maxItems: 10
};
provider.$get = function () {
var someList = new someListService(provider.defaults.maxItems);
return someList;
};
}
}
Funkcje dostawcy:
.service
lub dwóch .factory
metod.$get
To funkcja, która jest przyłączona bezpośrednio do instancji dostawcy. Ta funkcja jest funkcją fabryczną . Innymi słowy, jest to po prostu jak ten, którego używamy, aby dostarczyć do .factory
metody. W tej funkcji tworzymy własną usługę. Ta $get
właściwość, która jest funkcją, czyni dostawcę dostawcą . AngularJS oczekuje od dostawcy posiadania właściwości $ get, której wartość jest funkcją, którą Angular będzie traktował jako funkcję fabryczną. Ale to, co czyni tę konfigurację całego dostawcy bardzo wyjątkową, to fakt, że możemy udostępnić jakiś config
obiekt wewnątrz dostawcy usług, i który zwykle zawiera wartości domyślne, które możemy później zastąpić w kroku, w którym możemy skonfigurować całą aplikację.Fabryka: Fabryka, w której faktycznie tworzysz obiekt w fabryce i oddajesz go.
usługa: usługa, którą masz po prostu standardową funkcją, która używa tego słowa kluczowego do zdefiniowania funkcji.
dostawca: dostawca ma zdefiniowaną przez ciebie $ get i można go użyć do uzyskania obiektu, który zwraca dane.
Zasadniczo Dostawca, Fabryka i Usługa to wszystkie Usługi. Fabryka to szczególny przypadek Usługi, gdy wszystko czego potrzebujesz to funkcja $ get (), która pozwala napisać ją z mniejszym kodem.
Główne różnice między usługami, fabrykami i dostawcami to ich złożoność. Usługi są najprostszą formą, fabryki są nieco bardziej niezawodne, a dostawców można konfigurować w czasie wykonywania.
Oto podsumowanie, kiedy użyć każdego z nich:
Fabryka : Podana wartość musi zostać obliczona na podstawie innych danych.
Usługa : Zwracasz obiekt metodami.
Dostawca : Chcesz mieć możliwość skonfigurowania podczas fazy konfiguracji obiektu, który zostanie utworzony przed jego utworzeniem. Użyj dostawcy głównie w konfiguracji aplikacji, zanim aplikacja zostanie w pełni zainicjowana.
1.Usługi są obiektami singletonowymi, które są tworzone w razie potrzeby i nigdy nie są czyszczone do końca cyklu życia aplikacji (gdy przeglądarka jest zamknięta). Kontrolery są niszczone i czyszczone, gdy nie są już potrzebne.
2. Najłatwiejszym sposobem utworzenia usługi jest użycie metody factory (). Metoda factory () pozwala nam zdefiniować usługę, zwracając obiekt zawierający funkcje serwisowe i dane serwisowe. Funkcja definicji usługi to miejsce, w którym umieszczamy nasze usługi do wstrzykiwania, takie jak $ http i $ q. Dawny:
angular.module('myApp.services')
.factory('User', function($http) { // injectables go here
var backendUrl = "http://localhost:3000"; var service = {
// our factory definition
user: {},
setName: function(newName) {
service.user['name'] = newName;
},
setEmail: function(newEmail) { service.user['email'] = newEmail;
},
save: function() {
return $http.post(backendUrl + '/users', { user: service.user
}); }
};
return service; });
Korzystanie z fabryki () w naszej aplikacji
Łatwo jest korzystać z fabryki w naszej aplikacji, ponieważ możemy po prostu wstrzyknąć ją tam, gdzie jest potrzebna w czasie wykonywania.
angular.module('myApp')
.controller('MainController', function($scope, User) {
$scope.saveUser = User.save;
});
Różnica polega na cukrze syntaktycznym . Potrzebny jest tylko dostawca. Innymi słowy, tylko dostawca jest rzeczywisty kątowy, wszystkie pozostałe są wyprowadzane (w celu zmniejszenia kodu). Istnieje również prosta wersja o nazwie Value (), która zwraca tylko wartość, brak obliczeń lub funkcji. Nawet wartość pochodzi od dostawcy!
Skąd więc takie komplikacje, dlaczego nie możemy po prostu skorzystać z usługodawcy i zapomnieć o wszystkim innym? Ma nam pomóc w łatwym pisaniu kodu i lepszej komunikacji. I odpowiedź byłaby trudna, im bardziej skomplikowana, tym lepsza będzie sprzedaż ram.
Zastrzyk kątowy daje nam pierwszą wskazówkę, jak dojść do tego wniosku.
„$ injector służy do pobierania instancji obiektów zdefiniowanych przez dostawcę ”, nie usługa, nie fabryka, ale dostawca.
Lepszą odpowiedzią byłoby: „Usługa Angular jest tworzona przez fabrykę usług. Te fabryki usług to funkcje, które z kolei są tworzone przez usługodawcę. Dostawcy usług są funkcjami konstruktora. Po utworzeniu instancji muszą zawierać właściwość o nazwie $ get, która pełni funkcję fabryki usług. ”
Więc główny dostawca i wtryskiwacz i wszystko się ułoży :). Interesujące staje się w Typescript, kiedy $ get można zaimplementować u dostawcy, dziedzicząc po IServiceProvider.