Was sind die Unterschiede zwischen einem Service
, Provider
und Factory
in AngularJS?
service.factory
. Ich wollte dieses Thema nicht weiter komplizieren.
Was sind die Unterschiede zwischen einem Service
, Provider
und Factory
in AngularJS?
service.factory
. Ich wollte dieses Thema nicht weiter komplizieren.
Antworten:
Von der AngularJS-Mailingliste habe ich einen erstaunlichen Thread erhalten , der Service gegen Fabrik gegen Anbieter und deren Injektionsnutzung erklärt. Zusammenstellung der Antworten:
Syntax: module.service( 'serviceName', function );
Ergebnis: Wenn Sie serviceName als injizierbares Argument deklarieren, erhalten Sie eine Instanz der Funktion. Mit anderen Worten new FunctionYouPassedToService()
.
Syntax: module.factory( 'factoryName', function );
Ergebnis: Wenn Sie factoryName als injizierbares Argument deklarieren, erhalten Sie den Wert, der durch Aufrufen der an module.factory übergebenen Funktionsreferenz zurückgegeben wird .
Syntax: module.provider( 'providerName', function );
Ergebnis: Beim Deklarieren von providerName als injizierbares Argument Sie (new ProviderFunction()).$get()
. Die Konstruktorfunktion wird instanziiert, bevor die $ get-Methode aufgerufen wird - ProviderFunction
ist die an module.provider übergebene Funktionsreferenz.
Anbieter haben den Vorteil, dass sie während der Modulkonfigurationsphase konfiguriert werden können.
Sehen Sie hier für den bereitgestellten Code.
Hier ist eine großartige weitere Erklärung von Misko:
provide.value('a', 123);
function Controller(a) {
expect(a).toEqual(123);
}
In diesem Fall gibt der Injektor den Wert einfach so zurück, wie er ist. Aber was ist, wenn Sie den Wert berechnen möchten? Dann benutzen Sie eine Fabrik
provide.factory('b', function(a) {
return a*2;
});
function Controller(b) {
expect(b).toEqual(246);
}
So factory
ist eine Funktion, die für die Wertschöpfung verantwortlich ist. Beachten Sie, dass die Factory-Funktion nach anderen Abhängigkeiten fragen kann.
Aber was ist, wenn Sie mehr OO sein und eine Klasse namens Greeter haben möchten?
function Greeter(a) {
this.greet = function() {
return 'Hello ' + a;
}
}
Dann müssten Sie schreiben, um zu instanziieren
provide.factory('greeter', function(a) {
return new Greeter(a);
});
Dann könnten wir in einem solchen Controller nach einem Begrüßer fragen
function Controller(greeter) {
expect(greeter instanceof Greeter).toBe(true);
expect(greeter.greet()).toEqual('Hello 123');
}
Aber das ist viel zu wortreich. Ein kürzerer Weg, dies zu schreiben, wäreprovider.service('greeter', Greeter);
Aber was ist, wenn wir die Greeter
Klasse vor der Injektion konfigurieren wollten ? Dann könnten wir schreiben
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);
};
});
Dann können wir das machen:
angular.module('abc', []).config(function(greeter2Provider) {
greeter2Provider.setSalutation('Halo');
});
function Controller(greeter2) {
expect(greeter2.greet()).toEqual('Halo 123');
}
Als Randbemerkung, service
, factory
, und value
sind alle von Anbietern abgeleitet.
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
und greeter.Greet
ist. Warum nicht etwas Realeres und Relatierbares verwenden?
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
Kontext in der $get
Funktion nicht? - Sie verweisen in dieser Funktion nicht mehr auf den instanziierten Anbieter.
this
Kontext nicht, da aufgerufen wird new Provider()
. $ Get (), an Provider
den die Funktion übergeben wird app.provider
. Das heißt , dass $get()
als ein Verfahren auf dem konstruierten aufgerufen wird Provider
, so this
beziehen sich auf Provider
wie das Beispiel zeigt.
Unknown provider: helloWorldProvider <- helloWorld
wenn ich das lokal ausführe? Auskommentieren, gleicher Fehler für die anderen 2 Beispiele. Gibt es eine versteckte Anbieterkonfiguration? (Angular 1.0.8) - Gefunden: stackoverflow.com/questions/12339272/…
TL; DR
1) Wenn Sie eine Factory verwenden , erstellen Sie ein Objekt, fügen Eigenschaften hinzu und geben dasselbe Objekt zurück. Wenn Sie diese Factory an Ihren Controller übergeben, sind diese Eigenschaften für das Objekt jetzt in diesem Controller über Ihre Factory verfügbar.
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) Wenn Sie Service verwenden , instanziiert AngularJS ihn hinter den Kulissen mit dem Schlüsselwort 'new'. Aus diesem Grund fügen Sie 'this' Eigenschaften hinzu, und der Dienst gibt 'this' zurück. Wenn Sie den Dienst an Ihren Controller übergeben, sind diese Eigenschaften für "this" jetzt über Ihren Dienst auf diesem Controller verfügbar.
app.controller(‘myServiceCtrl’, function($scope, myService){
$scope.artist = myService.getArtist();
});
app.service(‘myService’, function(){
var _artist = ‘Nelly’;
this.getArtist = function(){
return _artist;
}
});
3) Anbieter sind der einzige Dienst, den Sie an Ihre .config () - Funktion übergeben können. Verwenden Sie einen Anbieter, wenn Sie eine modulweite Konfiguration für Ihr Serviceobjekt bereitstellen möchten, bevor Sie es verfügbar machen.
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’;
});
Nicht TL; DR
1) Factory
Factories sind die beliebteste Methode zum Erstellen und Konfigurieren eines Dienstes. Es gibt wirklich nicht viel mehr als das, was die TL gesagt hat; DR. Sie erstellen einfach ein Objekt, fügen ihm Eigenschaften hinzu und geben dasselbe Objekt zurück. Wenn Sie dann die Factory an Ihren Controller übergeben, sind diese Eigenschaften für das Objekt jetzt in diesem Controller über Ihre Factory verfügbar. Ein ausführlicheres Beispiel finden Sie unten.
app.factory(‘myFactory’, function(){
var service = {};
return service;
});
Jetzt stehen uns alle Eigenschaften zur Verfügung, die wir an 'service' anhängen, wenn wir 'myFactory' an unseren Controller übergeben.
Fügen wir nun unserer Rückruffunktion einige 'private' Variablen hinzu. Auf diese kann vom Controller aus nicht direkt zugegriffen werden, aber wir werden eventuell einige Getter / Setter-Methoden für 'service' einrichten, um diese 'privaten' Variablen bei Bedarf ändern zu können.
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;
});
Hier werden Sie feststellen, dass wir diese Variablen / Funktionen nicht an 'service' anhängen. Wir erstellen sie einfach, um sie später entweder zu verwenden oder zu ändern.
Nachdem unsere Hilfs- / privaten Variablen und Funktionen vorhanden sind, fügen wir dem 'service'-Objekt einige Eigenschaften hinzu. Was auch immer wir auf "Service" setzen, kann direkt in jedem Controller verwendet werden, an den wir "myFactory" übergeben.
Wir werden setArtist- und getArtist-Methoden erstellen, die den Künstler einfach zurückgeben oder festlegen. Wir werden auch eine Methode erstellen, die die iTunes-API mit unserer erstellten URL aufruft. Diese Methode wird ein Versprechen zurückgeben, das erfüllt wird, sobald die Daten von der iTunes-API zurückgegeben wurden. Wenn Sie nicht viel Erfahrung mit Versprechungen in AngularJS haben, empfehle ich Ihnen dringend, sich eingehend mit ihnen zu befassen.
Unten akzeptiert setArtist einen Künstler und ermöglicht es Ihnen, den Künstler festzulegen . getArtist gibt den Künstler zurück. callItunes ruft zuerst makeUrl () auf, um die URL zu erstellen, die wir für unsere $ http-Anfrage verwenden. Anschließend wird ein Versprechungsobjekt eingerichtet, eine $ http-Anfrage mit unserer endgültigen URL gestellt. Da $ http ein Versprechen zurückgibt, können wir nach unserer Anfrage .success oder .error aufrufen. Wir lösen dann unser Versprechen mit den iTunes-Daten oder lehnen es mit der Meldung "Es ist ein Fehler aufgetreten" ab.
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;
});
Jetzt ist unsere Fabrik fertig. Wir können jetzt 'myFactory' in jeden Controller einfügen und dann unsere Methoden aufrufen, die wir an unser Serviceobjekt angehängt haben (setArtist, getArtist und 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);
})
}
});
Im obigen Controller injizieren wir den 'myFactory'-Dienst. Anschließend legen wir Eigenschaften für unser $ scope-Objekt mit Daten aus 'myFactory' fest. Der einzige schwierige Code oben ist, wenn Sie sich noch nie mit Versprechungen befasst haben. Da callItunes ein Versprechen zurückgibt, können wir die .then () -Methode verwenden und $ scope.data.artistData erst festlegen, wenn unser Versprechen mit den iTunes-Daten erfüllt ist. Sie werden feststellen, dass unser Controller sehr dünn ist (dies ist eine gute Codierungspraxis). Alle unsere logischen und persistenten Daten befinden sich in unserem Service, nicht in unserem Controller.
2) Service
Das vielleicht Wichtigste, was Sie beim Erstellen eines Dienstes wissen müssen, ist, dass er mit dem Schlüsselwort "Neu" instanziiert wird. Für Ihre JavaScript-Gurus sollte dies einen großen Hinweis auf die Art des Codes geben. Für diejenigen unter Ihnen mit eingeschränktem Hintergrund in JavaScript oder für diejenigen, die nicht genau wissen, was das 'neue' Schlüsselwort tatsächlich bewirkt, lassen Sie uns einige JavaScript-Grundlagen überprüfen, die uns letztendlich helfen, die Natur eines Dienstes zu verstehen.
Um die Änderungen wirklich zu sehen, die auftreten, wenn Sie eine Funktion mit dem Schlüsselwort 'new' aufrufen, erstellen wir eine Funktion und rufen sie mit dem Schlüsselwort 'new' auf. Zeigen wir dann, was der Interpreter tut, wenn er das Schlüsselwort 'new' sieht. Die Endergebnisse sind beide gleich.
Lassen Sie uns zuerst unseren Konstruktor erstellen.
var Person = function(name, age){
this.name = name;
this.age = age;
}
Dies ist eine typische JavaScript-Konstruktorfunktion. Wenn wir nun die Person-Funktion mit dem Schlüsselwort 'new' aufrufen, wird 'this' an das neu erstellte Objekt gebunden.
Fügen wir nun dem Prototyp unserer Person eine Methode hinzu, damit sie für jede Instanz unserer Personenklasse verfügbar ist.
Person.prototype.sayName = function(){
alert(‘My name is ‘ + this.name);
}
Da wir nun die Funktion sayName auf den Prototyp setzen, kann jede Instanz von Person die Funktion sayName aufrufen, um den Namen dieser Instanz zu warnen.
Nachdem wir nun unsere Person-Konstruktorfunktion und unsere sayName-Funktion in ihrem Prototyp haben, erstellen wir tatsächlich eine Instanz von Person und rufen dann die sayName-Funktion auf.
var tyler = new Person(‘Tyler’, 23);
tyler.sayName(); //alerts ‘My name is Tyler’
Insgesamt sieht der Code zum Erstellen eines Personenkonstruktors, zum Hinzufügen einer Funktion zum Prototyp, zum Erstellen einer Personeninstanz und zum anschließenden Aufrufen der Funktion für den Prototyp folgendermaßen aus.
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’
Schauen wir uns nun an, was tatsächlich passiert, wenn Sie das Schlüsselwort 'new' in JavaScript verwenden. Das erste, was Sie beachten sollten, ist, dass wir nach der Verwendung von 'new' in unserem Beispiel eine Methode (sayName) für 'tyler' aufrufen können, als wäre es ein Objekt - das liegt daran, dass es so ist. Zuerst wissen wir also, dass unser Personenkonstruktor ein Objekt zurückgibt, ob wir das im Code sehen können oder nicht. Zweitens wissen wir, dass das Objekt, das die Person-Funktion zurückgibt, bei fehlgeschlagenen Suchvorgängen an ihren Prototyp delegieren muss, da sich unsere Funktion sayName auf dem Prototyp und nicht direkt auf der Person-Instanz befindet. Einfacher ausgedrückt, wenn wir tyler.sayName () aufrufen, sagt der Interpreter: „OK, ich werde das soeben erstellte 'tyler'-Objekt betrachten, die Funktion sayName suchen und es dann aufrufen. Moment mal, ich sehe es hier nicht - alles was ich sehe ist Name und Alter, Lassen Sie mich den Prototyp überprüfen. Ja, es sieht so aus, als wäre es auf dem Prototyp, lass es mich nennen. “
Unten finden Sie Code, wie Sie darüber nachdenken können, was das 'neue' Schlüsselwort in JavaScript tatsächlich tut. Es ist im Grunde ein Codebeispiel für den obigen Absatz. Ich habe die 'Interpreter-Ansicht' oder die Art und Weise, wie der Interpreter den Code sieht, in Notizen eingefügt.
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;
}
Wenn Sie nun wissen, was das 'neue' Schlüsselwort in JavaScript wirklich bewirkt, sollte es einfacher sein, einen Dienst in AngularJS zu erstellen.
Das Wichtigste, was Sie beim Erstellen eines Dienstes verstehen müssen, ist zu wissen, dass Dienste mit dem Schlüsselwort "Neu" instanziiert werden. Wenn Sie dieses Wissen mit unseren obigen Beispielen kombinieren, sollten Sie jetzt erkennen, dass Sie Ihre Eigenschaften und Methoden direkt an 'this' anhängen, das dann vom Service selbst zurückgegeben wird. Schauen wir uns das in Aktion an.
Im Gegensatz zu dem, was wir ursprünglich mit dem Factory-Beispiel gemacht haben, müssen wir kein Objekt erstellen und dann dieses Objekt zurückgeben, da wir, wie bereits mehrfach erwähnt, das Schlüsselwort 'new' verwendet haben, damit der Interpreter dieses Objekt erstellt und es delegieren lässt Es ist ein Prototyp und wird dann für uns zurückgegeben, ohne dass wir die Arbeit erledigen müssen.
Lassen Sie uns zuerst unsere 'private' und Hilfsfunktion erstellen. Dies sollte sehr vertraut aussehen, da wir mit unserer Fabrik genau dasselbe gemacht haben. Ich werde hier nicht erklären, was jede Zeile tut, da ich das im Fabrikbeispiel getan habe. Wenn Sie verwirrt sind, lesen Sie das Fabrikbeispiel erneut.
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;
}
});
Jetzt werden wir alle unsere Methoden, die in unserem Controller verfügbar sein werden, an 'this' anhängen.
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;
}
});
Genau wie in unserer Factory sind setArtist, getArtist und callItunes jetzt in jedem Controller verfügbar, an den wir myService übergeben. Hier ist der myService-Controller (der fast genau dem unseres werkseitigen Controllers entspricht).
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);
})
}
});
Wie ich bereits erwähnt habe, sind Services, sobald Sie wirklich verstanden haben, was "neu" macht, fast identisch mit Fabriken in AngularJS.
3) Anbieter
Das Wichtigste an Anbietern ist, dass sie der einzige Dienst sind, den Sie an den Teil app.config Ihrer Anwendung übergeben können. Dies ist von großer Bedeutung, wenn Sie einen Teil Ihres Serviceobjekts ändern müssen, bevor es überall in Ihrer Anwendung verfügbar ist. Obwohl Services / Fabriken sehr ähnlich sind, gibt es einige Unterschiede, die wir diskutieren werden.
Zuerst haben wir unseren Provider auf ähnliche Weise eingerichtet wie bei unserem Service und unserer Fabrik. Die folgenden Variablen sind unsere 'private' und Hilfsfunktion.
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;
}
}
* Wenn ein Teil des obigen Codes verwirrend ist, lesen Sie den Abschnitt Factory, in dem ich erkläre, was das alles bewirkt.
Sie können sich Anbieter mit drei Abschnitten vorstellen. Der erste Abschnitt enthält die 'privaten' Variablen / Funktionen, die später geändert / festgelegt werden (siehe oben). Der zweite Abschnitt enthält die Variablen / Funktionen, die in Ihrer app.config-Funktion verfügbar sind und daher geändert werden können, bevor sie an anderer Stelle verfügbar sind (siehe auch oben). Es ist wichtig zu beachten, dass diese Variablen an das Schlüsselwort 'this' angehängt werden müssen. In unserem Beispiel kann nur 'thingFromConfig' in der app.config geändert werden. Der dritte Abschnitt (siehe unten) enthält alle Variablen / Funktionen, die in Ihrem Controller verfügbar sind, wenn Sie den Dienst 'myProvider' an diesen bestimmten Controller übergeben.
Wenn Sie einen Dienst mit Provider erstellen, sind die einzigen Eigenschaften / Methoden, die in Ihrem Controller verfügbar sind, die Eigenschaften / Methoden, die von der Funktion $ get () zurückgegeben werden. Der folgende Code setzt $ get auf 'this' (von dem wir wissen, dass es irgendwann von dieser Funktion zurückgegeben wird). Diese $ get-Funktion gibt nun alle Methoden / Eigenschaften zurück, die im Controller verfügbar sein sollen. Hier ist ein Codebeispiel.
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
}
}
Jetzt sieht der vollständige Provider-Code so aus
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
}
}
});
Jetzt sind setArtist, getArtist und callItunes genau wie in unserer Factory und in unserem Service in jedem Controller verfügbar, an den wir myProvider übergeben. Hier ist der myProvider-Controller (der fast genau mit unserem Werks- / Service-Controller identisch ist).
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;
});
Wie bereits erwähnt, besteht der Sinn des Erstellens eines Dienstes mit Provider darin, einige Variablen über die Funktion app.config ändern zu können, bevor das endgültige Objekt an den Rest der Anwendung übergeben wird. Sehen wir uns ein Beispiel dafür an.
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';
});
Jetzt können Sie sehen, wie 'thingFromConfig' in unserem Provider als leere Zeichenfolge ist, aber wenn dies im DOM angezeigt wird, lautet es 'Dieser Satz wurde gesetzt ...'.
Alle Dienste sind Singletons ; Sie werden einmal pro App instanziiert. Sie können von jedem Typ sein , sei es ein Grundelement, ein Objektliteral, eine Funktion oder sogar eine Instanz eines benutzerdefinierten Typs.
Die value
, factory
, service
, constant
, und provider
Methoden sind alle Anbieter. Sie bringen dem Injektor bei, wie die Dienste instanziiert werden.
Das ausführlichste, aber auch umfassendste ist ein Anbieterrezept. Die verbleibenden vier Rezepttypen - Wert, Fabrik, Service und Konstante - sind nur syntaktischer Zucker über einem Anbieterrezept .
Sie sollten das Provider-Rezept nur verwenden, wenn Sie eine API für die anwendungsweite Konfiguration verfügbar machen möchten, die vor dem Start der Anwendung vorgenommen werden muss. Dies ist normalerweise nur für wiederverwendbare Dienste interessant, deren Verhalten zwischen den Anwendungen möglicherweise geringfügig variieren muss.
decorator
.Grundlegendes zu AngularJS Factory, Service und Provider
All dies wird verwendet, um wiederverwendbare Singleton-Objekte gemeinsam zu nutzen. Es hilft, wiederverwendbaren Code für Ihre App / verschiedene Komponenten / Module freizugeben.
Vom Docs Service / Factory :
- Faul instanziiert - Angular instanziiert einen Service / eine Factory nur dann, wenn eine Anwendungskomponente davon abhängt.
- Singletons - Jede von einem Service abhängige Komponente erhält einen Verweis auf die einzelne Instanz, die von der Service Factory generiert wurde.
Eine Factory ist eine Funktion, bei der Sie Logik bearbeiten / hinzufügen können, bevor Sie ein Objekt erstellen. Anschließend wird das neu erstellte Objekt zurückgegeben.
app.factory('MyFactory', function() {
var serviceObj = {};
//creating an object with methods/functions or variables
serviceObj.myFunction = function() {
//TO DO:
};
//return that object
return serviceObj;
});
Verwendungszweck
Es kann nur eine Sammlung von Funktionen wie eine Klasse sein. Daher kann es in verschiedenen Controllern instanziiert werden, wenn Sie es in Ihre Controller- / Factory- / Direktivenfunktionen einspeisen. Es wird nur einmal pro App instanziiert.
Denken Sie beim Betrachten der Dienste einfach an den Array-Prototyp. Ein Dienst ist eine Funktion, die ein neues Objekt mit dem Schlüsselwort 'new' instanziiert. Mit dem this
Schlüsselwort können Sie einem Serviceobjekt Eigenschaften und Funktionen hinzufügen . Im Gegensatz zu einer Factory wird nichts zurückgegeben (es wird ein Objekt zurückgegeben, das Methoden / Eigenschaften enthält).
app.service('MyService', function() {
//directly binding events to this context
this.myServiceFunction = function() {
//TO DO:
};
});
Verwendungszweck
Verwenden Sie diese Option, wenn Sie ein einzelnes Objekt in der gesamten Anwendung freigeben müssen. Zum Beispiel authentifizierte Benutzerdetails, gemeinsam nutzbare Methoden / Daten, Dienstprogrammfunktionen usw.
Ein Anbieter wird verwendet, um ein konfigurierbares Dienstobjekt zu erstellen. Sie können die Serviceeinstellung über die Konfigurationsfunktion konfigurieren. Mit der $get()
Funktion wird ein Wert zurückgegeben . Die $get
Funktion wird in der Laufphase im Winkel ausgeführt.
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.
};
};
});
Verwendungszweck
Wenn Sie eine modulweise Konfiguration für Ihr Serviceobjekt bereitstellen müssen, bevor Sie es verfügbar machen, z. Angenommen , Sie wie Ihre API URL auf Grundlage Ihrer Umgebung einstellen möchten dev
, stage
oderprod
HINWEIS
In der Konfigurationsphase von Angular ist nur ein Anbieter verfügbar, Service & Factory jedoch nicht.
Ich hoffe, dies hat Ihr Verständnis für Fabrik, Service und Anbieter geklärt .
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
, klingt also nicht möglich, oder?
Für mich kam die Offenbarung, als mir klar wurde, dass sie alle auf die gleiche Weise funktionieren: indem sie etwas einmal ausführen, den Wert speichern, den sie erhalten, und dann denselben gespeicherten Wert abhusten, wenn sie durch Abhängigkeitsinjektion referenziert werden .
Sagen wir, wir haben:
app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);
Der Unterschied zwischen den drei ist:
a
Der gespeicherte Wert stammt aus dem Betrieb fn
.b
Der gespeicherte Wert stammt von new
ing fn
.c
‚s gespeicherten Wert kommt aus dem ersten Instanz immer durch new
ing fn
, und dann eine laufende $get
Methode der Instanz.Das heißt, es gibt so etwas wie ein Cache-Objekt in AngularJS, dessen Wert jeder Injektion nur einmal zugewiesen wird, wenn sie das erste Mal injiziert wurden und wo:
cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()
Aus diesem Grund verwenden wir this
in Diensten und definieren einen this.$get
in Anbietern.
factory
s. Der einzige Grund dafür service
sind Sprachen wie CoffeeScript, TypeScript, ES6 usw., sodass Sie deren Klassensyntax verwenden können. Sie benötigen provider
s nur, wenn Ihr Modul in mehreren Anwendungen mit unterschiedlichen Einstellungen verwendet wird app.config()
. Ob Ihr Dienst ein reiner Singleton ist oder Instanzen von etwas erstellen kann, hängt nur von Ihrer Implementierung ab.
Service gegen Anbieter gegen Fabrik:
Ich versuche es einfach zu halten. Es geht um das grundlegende JavaScript-Konzept.
Lassen Sie uns zunächst über Dienste in AngularJS sprechen !
Was ist Service: In AngularJS, Serviceist nichts anderes als ein Singleton-JavaScript-Objekt, in dem einige nützliche Methoden oder Eigenschaften gespeichert werden können. Dieses Singleton-Objekt wird auf ngApp-Basis (Angular App) erstellt und von allen Controllern in der aktuellen App gemeinsam genutzt. Wenn Angularjs ein Dienstobjekt instanziiert, registriert es dieses Dienstobjekt mit einem eindeutigen Dienstnamen. Jedes Mal, wenn wir eine Dienstinstanz benötigen, durchsucht Angular die Registrierung nach diesem Dienstnamen und gibt den Verweis auf das Dienstobjekt zurück. So können wir Methoden aufrufen, auf Eigenschaften usw. für das Serviceobjekt zugreifen. Möglicherweise haben Sie die Frage, ob Sie auch Eigenschaften und Methoden für das Bereichsobjekt von Controllern festlegen können! Warum brauchen Sie ein Serviceobjekt? Die Antwort lautet: Dienste werden von mehreren Controllern gemeinsam genutzt. Wenn Sie einige Eigenschaften / Methoden in das Bereichsobjekt eines Controllers einfügen, ist es nur für den aktuellen Bereich verfügbar.
Wenn es also drei Controller-Bereiche gibt, seien es ControllerA, ControllerB und ControllerC, die alle dieselbe Dienstinstanz verwenden.
<div ng-controller='controllerA'>
<!-- controllerA scope -->
</div>
<div ng-controller='controllerB'>
<!-- controllerB scope -->
</div>
<div ng-controller='controllerC'>
<!-- controllerC scope -->
</div>
Wie erstelle ich einen Service?
AngularJS bietet verschiedene Methoden zum Registrieren eines Dienstes. Hier konzentrieren wir uns auf drei Methoden Fabrik (..), Service (..), Anbieter (..);
Verwenden Sie diesen Link als Code-Referenz
Wir können eine Factory-Funktion wie folgt definieren.
factory('serviceName',function fnFactory(){ return serviceInstance;})
AngularJS bietet die Methode 'factory (' serviceName ', fnFactory)' , die zwei Parameter verwendet, serviceName und eine JavaScript-Funktion. Angular erstellt eine Dienstinstanz durch Aufrufen der Funktion fnFactory () wie unten.
var serviceInstace = fnFactory();
Die übergebene Funktion kann ein Objekt definieren und dieses Objekt zurückgeben. AngularJS speichert diese Objektreferenz einfach in einer Variablen, die als erstes Argument übergeben wird. Alles, was von fnFactory zurückgegeben wird, ist an serviceInstance gebunden. Anstatt ein Objekt zurückzugeben, können wir auch Funktionen, Werte usw. zurückgeben. Was auch immer wir zurückgeben, es steht der Dienstinstanz zur Verfügung.
Beispiel:
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(){})
Auf die andere Weise können wir einen Dienst registrieren. Der einzige Unterschied besteht darin, wie AngularJS versucht, das Serviceobjekt zu instanziieren. Dieses Mal verwendet angle das Schlüsselwort 'new' und ruft die Konstruktorfunktion wie folgt auf.
var serviceInstance = new fnServiceConstructor();
In der Konstruktorfunktion können wir das Schlüsselwort 'this' verwenden, um dem Serviceobjekt Eigenschaften / Methoden hinzuzufügen. Beispiel:
//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);
};
});
Die Funktion Provider () ist eine weitere Möglichkeit zum Erstellen von Diensten. Lassen Sie uns daran interessiert sein, einen Dienst zu erstellen, der dem Benutzer nur eine Begrüßungsnachricht anzeigt. Wir möchten aber auch eine Funktionalität bereitstellen, mit der der Benutzer seine eigene Begrüßungsnachricht festlegen kann. In technischer Hinsicht wollen wir konfigurierbare Dienste erstellen. Wie können wir das machen? Es muss einen Weg geben, damit die App ihre benutzerdefinierten Begrüßungsnachrichten weitergeben kann und Angularjs sie der Factory- / Konstruktorfunktion zur Verfügung stellt, die unsere Service-Instanz erstellt. In einem solchen Fall erledigt die Funktion provider () den Job. Mit der Funktion provider () können wir konfigurierbare Dienste erstellen.
Wir können konfigurierbare Dienste mithilfe der unten angegebenen Anbietersyntax erstellen.
/*step1:define a service */
app.provider('service',function serviceProviderConstructor(){});
/*step2:configure the service */
app.config(function configureService(serviceProvider){});
1. Das Provider-Objekt wird mit der Konstruktorfunktion erstellt, die wir in unserer Provider-Funktion definiert haben.
var serviceProvider = new serviceProviderConstructor();
2.Die Funktion, die wir in app.config () übergeben haben, wird ausgeführt. Dies wird als Konfigurationsphase bezeichnet, und hier haben wir die Möglichkeit, unseren Service anzupassen.
configureService(serviceProvider);
3.Die endgültige Service-Instanz wird durch Aufrufen der $ get-Methode von serviceProvider erstellt.
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 ?');
}
);
Zusammenfassung:
Factory verwendet eine Factory-Funktion, die eine Service-Instanz zurückgibt. serviceInstance = fnFactory ();
Der Dienst verwendet eine Konstruktorfunktion, und Angular ruft diese Konstruktorfunktion mit dem Schlüsselwort 'new' zum Erstellen der Dienstinstanz auf. serviceInstance = new fnServiceConstructor ();
Provider definiert eine providerConstructor-Funktion. Diese providerConstructor-Funktion definiert eine Factory-Funktion $ get . Angular ruft $ get () auf, um das Serviceobjekt zu erstellen. Die Anbietersyntax bietet den zusätzlichen Vorteil, dass das Serviceobjekt konfiguriert wird, bevor es instanziiert wird. serviceInstance = $ get ();
Wie von mehreren Leuten hier richtig hervorgehoben, sind eine Fabrik, ein Anbieter, ein Service und sogar ein Wert und eine Konstante Versionen derselben Sache. Sie können das Allgemeinere provider
in alle zerlegen . Wie so:
Hier ist der Artikel, aus dem dieses Bild stammt:
Wenn Sie AngularJS eine Funktion geben, wird AngularJS den Rückgabewert zwischenspeichern und einfügen, wenn die Factory angefordert wird.
Beispiel:
app.factory('factory', function() {
var name = '';
// Return value **is** the object that will be injected
return {
name: name;
}
})
Verwendungszweck:
app.controller('ctrl', function($scope, factory) {
$scope.name = factory.name;
});
Sie geben AngularJS eine Funktion, AngularJS ruft new auf, um sie zu instanziieren. Es ist die von AngularJS erstellte Instanz, die zwischengespeichert und injiziert wird, wenn der Dienst angefordert wird. Da new zum Instanziieren des Dienstes verwendet wurde, ist das Schlüsselwort this gültig und bezieht sich auf die Instanz.
Beispiel:
app.service('service', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.getName = function() {
return name;
}
});
Verwendungszweck:
app.controller('ctrl', function($scope, service) {
$scope.name = service.getName();
});
Sie geben AngularJS eine Funktion, und AngularJS ruft seine $get
Funktion auf. Dies ist der Rückgabewert der $get
Funktion, der zwischengespeichert und eingefügt wird, wenn der Dienst angefordert wird.
Mit Providern können Sie den Provider konfigurieren, bevor AngularJS die $get
Methode zum Abrufen des Injectible aufruft.
Beispiel:
app.provider('provider', function() {
var name = '';
this.setName = function(newName) {
name = newName;
}
this.$get = function() {
return {
name: name
}
}
})
Verwendung (als Injektionslösung in einer Steuerung)
app.controller('ctrl', function($scope, provider) {
$scope.name = provider.name;
});
Verwendung (vorheriges Konfigurieren des Providers $get
wird aufgerufen, um das Injectable zu erstellen)
app.config(function(providerProvider) {
providerProvider.setName('John');
});
Beim Herumspielen mit Anbietern ist mir etwas Interessantes aufgefallen.
Die Sichtbarkeit von injizierbaren Substanzen ist für Anbieter anders als für Dienstleistungen und Fabriken. Wenn Sie eine AngularJS-Konstante deklarieren (z. B. myApp.constant('a', 'Robert');
), können Sie sie in Services, Fabriken und Anbieter einfügen.
Wenn Sie jedoch einen AngularJS-Wert deklarieren (z. B. myApp.value('b', {name: 'Jones'});
), können Sie ihn in Services und Fabriken einfügen, NICHT jedoch in die Funktion zum Erstellen von Anbietern. Sie können es jedoch in die $get
Funktion einfügen, die Sie für Ihren Anbieter definieren. Dies wird in der AngularJS-Dokumentation erwähnt, ist aber leicht zu übersehen. Sie finden es auf der Seite% bereitstellen in den Abschnitten über die Wert- und Konstantenmethoden.
<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>
Dies ist ein sehr verwirrender Teil für Neulinge und ich habe versucht, ihn in einfachen Worten zu klären
AngularJS-Dienst: Wird zum Teilen von Dienstprogrammfunktionen mit der Dienstreferenz in der Steuerung verwendet. Der Dienst ist von Natur aus Singleton, sodass für einen Dienst nur eine Instanz im Browser erstellt wird und auf der gesamten Seite dieselbe Referenz verwendet wird.
Im Service erstellen wir mit diesem Objekt Funktionsnamen als Eigenschaft .
AngularJS Factory: Der Zweck von Factory ist der gleiche wie Service. In diesem Fall erstellen wir jedoch ein neues Objekt und fügen Funktionen als Eigenschaften dieses Objekts hinzu. Am Ende geben wir dieses Objekt zurück.
AngularJS-Provider: Der Zweck ist wieder der gleiche, jedoch gibt der Provider die Ausgabe seiner $ get-Funktion an.
Das Definieren und Verwenden von Service, Factory und Provider wird unter http://www.dotnetfunda.com/articles/show/3156/difference-between-angularjs-service-factory-and-provider erläutert
Für mich ist der beste und einfachste Weg, den Unterschied zu verstehen:
var service, factory;
service = factory = function(injection) {}
Wie AngularJS bestimmte Komponenten instanziiert (vereinfacht):
// service
var angularService = new service(injection);
// factory
var angularFactory = factory(injection);
Für den Dienst wird die AngularJS-Komponente die Objektinstanz der Klasse, die durch die Dienstdeklarationsfunktion dargestellt wird. Für die Fabrik ist es das Ergebnis, das von der Fabrikdeklarationsfunktion zurückgegeben wird. Die Fabrik verhält sich möglicherweise genauso wie der Service:
var factoryAsService = function(injection) {
return new function(injection) {
// Service content
}
}
Die einfachste Denkweise ist die folgende:
Das Beispiel für die Factory-Klasse sowie die Unterschiede zwischen den Anbietern finden Sie in den Kommentaren.
new MyService()
oder so :)
Meine Klarstellung zu diesem Thema:
Grundsätzlich erstellen und konfigurieren alle genannten Typen (Service, Factory, Provider usw.) nur globale Variablen (die natürlich für die gesamte Anwendung global sind), so wie es altmodische globale Variablen waren.
Obwohl globale Variablen nicht empfohlen werden, besteht die tatsächliche Verwendung dieser globalen Variablen darin, eine Abhängigkeitsinjektion bereitzustellen , indem die Variable an den entsprechenden Controller übergeben wird.
Es gibt viele Komplikationen bei der Erstellung der Werte für die "globalen Variablen":
app.config
.
app.config
Datei festgelegt wurden, und diese $ .get- Funktion verhält sich genauso wie die Factory oben, indem sein Rückgabewert verwendet wird, um die "globalen" Variablen zu initialisieren. Mein Verständnis ist unten sehr einfach.
Fabrik: Sie erstellen einfach ein Objekt innerhalb der Fabrik und geben es zurück.
Bedienung:
Sie haben nur eine Standardfunktion, die dieses Schlüsselwort verwendet, um eine Funktion zu definieren.
Anbieter:
Es gibt ein $get
Objekt, das Sie definieren, und es kann verwendet werden, um das Objekt abzurufen, das Daten zurückgibt.
Zusammenfassung aus Angular-Dokumenten :
Beste Antworten von SO:
https://stackoverflow.com/a/26924234/165673 (<- GUT)
https://stackoverflow.com/a/27263882/165673
https://stackoverflow.com/a/16566144/165673
Alle guten Antworten schon. Ich möchte noch ein paar Punkte zu Service und Fabrik hinzufügen . Zusammen mit dem Unterschied zwischen Service / Fabrik. Und man kann auch Fragen haben wie:
Beginnen wir mit dem Unterschied zwischen Service und Werk:
Beide sind Singletons : Immer wenn Angular diese zum ersten Mal als Abhängigkeit findet, wird eine einzelne Instanz von Service / Factory erstellt. Sobald die Instanz erstellt wurde, wird dieselbe Instanz für immer verwendet.
Kann verwendet werden, um ein Objekt mit Verhalten zu modellieren : Beide können Methoden, interne Statusvariablen usw. haben. Die Art und Weise, wie Sie diesen Code schreiben, ist jedoch unterschiedlich.
Dienstleistungen:
Ein Service ist eine Konstruktorfunktion, die Angular durch Aufrufen von new instanziiert yourServiceName()
. Dies bedeutet ein paar Dinge.
this
.new yourServiceName(
, erhält es das this
Objekt mit allen Eigenschaften, die Sie darauf setzen.Beispielbeispiel:
angular.service('MyService', function() {
this.aServiceVariable = "Ved Prakash"
this.aServiceMethod = function() {
return //code
};
});
Wenn Angular diesen
MyService
Dienst in einen davon abhängigen ControllerMyService
einfügt, erhält dieser Controller einen , auf dem er Funktionen aufrufen kann, z. B. MyService.aServiceMethod ().
Seien Sie vorsichtig mitthis
:
Da der erstellte Dienst ein Objekt ist, können die darin enthaltenen Methoden beim Aufruf auf Folgendes verweisen:
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++;
};
});
Sie könnten versucht sein, ScoreKeeper.setScore
eine Versprechenskette aufzurufen , wenn Sie beispielsweise die Punktzahl initialisiert haben, indem Sie sie vom Server abgerufen haben : $http.get('/score').then(ScoreKeeper.setScore).
Das Problem dabei ist, dass ScoreKeeper.setScore
sie mit this
gebunden an aufgerufen wird null
und Sie Fehler erhalten. Der bessere Weg wäre $http.get('/score').then(ScoreKeeper.setScore.bind(ScoreKeeper))
. Ob Sie dies für Ihre Servicemethoden verwenden oder nicht, achten Sie darauf, wie Sie sie aufrufen.
Rückgabe eines Wertes von aService
:
Aufgrund der Funktionsweise von JavaScript-Konstruktoren erhält der Aufrufer dieses Objekt anstelle dieser Instanz , wenn Sie einen komplexen Wert (i.e., an Object)
von einer constructor
Funktion zurückgeben.
Dies bedeutet , dass Sie im Grunde das Werk Beispiel von unten copy-paste, ersetzen factory
mit service
, und es wird funktionieren:
angular.service('MyService', function($http) {
var api = {};
api.aServiceMethod= function() {
return $http.get('/users');
};
return api;
});
Wenn Angular Ihren Dienst mit neuem MyService () erstellt, erhält es dieses API-Objekt anstelle der MyService-Instanz.
Dies ist das Verhalten für komplexe Werte (Objekte, Funktionen), jedoch nicht für primitive Typen.
Fabriken:
Eine Factory ist eine einfache alte Funktion, die einen Wert zurückgibt. Der Rückgabewert ist das, was in Dinge injiziert wird, die von der Fabrik abhängen. Ein typisches Factory-Muster in Angular besteht darin, ein Objekt mit Funktionen als Eigenschaften wie folgt zurückzugeben:
angular.factory('MyFactory', function($http) {
var api = {};
api.aFactoryMethod= function() {
return $http.get('/users');
};
return api;
});
Der injizierte Wert für eine Factory-Abhängigkeit ist der Rückgabewert der Factory und muss kein Objekt sein. Es könnte eine Funktion sein
Antworten auf die obigen Fragen 1 und 2:
Meistens bleiben Sie einfach bei der Verwendung von Fabriken für alles. Ihr Verhalten ist leichter zu verstehen. Es gibt keine Wahl, ob ein Wert zurückgegeben werden soll oder nicht, und außerdem müssen keine Fehler eingeführt werden, wenn Sie das Falsche tun.
Ich bezeichne sie immer noch als "Dienste", wenn ich davon spreche, sie als Abhängigkeiten zu injizieren.
Das Service- / Fabrikverhalten ist sehr ähnlich, und einige Leute werden sagen, dass beide in Ordnung sind. Das ist etwas wahr, aber ich finde es einfacher, den Ratschlägen von John Papas Styleguide zu folgen und einfach bei den Fabriken zu bleiben. **
Eine zusätzliche Klarstellung ist, dass Fabriken Funktionen / Grundelemente erstellen können, während Services dies nicht können. Schau dir das an jsFiddle an, die auf Epokks basiert: http://jsfiddle.net/skeller88/PxdSP/1351/ .
Die Factory gibt eine Funktion zurück, die aufgerufen werden kann:
myApp.factory('helloWorldFromFactory', function() {
return function() {
return "Hello, World!";
};
});
Die Factory kann auch ein Objekt mit einer Methode zurückgeben, die aufgerufen werden kann:
myApp.factory('helloWorldFromFactory', function() {
return {
sayHello: function() {
return "Hello, World!";
}
};
});
Der Dienst gibt ein Objekt mit einer Methode zurück, die aufgerufen werden kann:
myApp.service('helloWorldFromService', function() {
this.sayHello = function() {
return "Hello, World!";
};
});
Weitere Informationen finden Sie in einem Beitrag, den ich über den Unterschied geschrieben habe: http://www.shanemkeller.com/tldr-services-vs-factories-in-angular/
Es gibt bereits gute Antworten, aber ich möchte diese nur teilen.
Zuallererst: Provider ist der Weg / das Rezept, um ein zu erstellenservice
(Singleton-Objekt) zu erstellen, das von $ injizier injiziert werden soll (wie AngulaJS mit dem IoC-Muster umgeht).
Und Wert, Fabrik, Service und Konstante (4 Wege) - der syntaktische Zucker über Provider Weg / Recepie.
Es wurde ein Service vs Factory
Teil behandelt:
https://www.youtube.com/watch?v=BLzNCkPn3ao
Beim Servicenew
dreht sich eigentlich alles um Schlüsselwörter, die bekanntlich vier Dinge bewirken:
prototype
Objektcontext
mitthis
this
Und Factory dreht sich alles um Factory Pattern - enthält Funktionen, die Objekte wie diesen Service zurückgeben.
Und dieses einfache / kurze Video: deckt auch den Anbieter ab : https://www.youtube.com/watch?v=HvTZbQ_hUZY (dort sehen Sie, wie sie von der Fabrik zum Anbieter gehen)
Das Anbieterrezept wird hauptsächlich in der App-Konfiguration verwendet, bevor die App vollständig gestartet / initialisiert wurde.
Nachdem ich all diese Beiträge gelesen hatte, war das für mich verwirrender. Aber dennoch sind alle Informationen wertvoll. Schließlich fand ich die folgende Tabelle, die Informationen mit einfachem Vergleich liefert
Und für Anfänger verstehen: - Dies kann den Anwendungsfall nicht korrigieren, aber auf hoher Ebene ist dies der Anwendungsfall für diese drei.
angular.module('myApp').config(function($testProvider){
$testProvider.someFunction();
})
Für grundlegende Szenarien verhält sich Factory & Service gleich.
Hier ist ein Broilerplate-Code, den ich als Code-Vorlage für die Objektfabrik in AngularjS entwickelt habe. Ich habe ein Auto / eine CarFactory als Beispiel verwendet, um dies zu veranschaulichen. Ermöglicht einfachen Implementierungscode in der Steuerung.
<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>
Hier ist ein einfacheres Beispiel. Ich verwende einige Bibliotheken von Drittanbietern, die ein "Position" -Objekt erwarten, das Breiten- und Längengrade anzeigt, jedoch über unterschiedliche Objekteigenschaften. Ich wollte den Herstellercode nicht hacken, also habe ich die "Position" -Objekte angepasst, die ich herumgereicht habe.
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
;;
Verwenden Sie als Referenz diese Seite und die Dokumentation (die sich seit meinem letzten Blick stark verbessert zu haben scheint) habe ich die folgende reale (-ish) Weltdemo zusammengestellt, die 4 der 5 Varianten des Anbieters verwendet. Wert, Konstante, Fabrik und ausgewachsener Anbieter.
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);
};
});
Arbeits Demo .
Diese Antwort befasst sich mit dem Thema / der Frage
ODER
im grunde was passiert ist
Wenn Sie ein factory()
it-Set erstellen, function
das Sie im zweiten Argument an den Provider angegeben haben, $get
und es zurückgeben ( provider(name, {$get:factoryFn })
), erhalten Sie nur, provider
aber es gibt keine andere Eigenschaft / Methode als$get
diese provider
(bedeutet, dass Sie dies nicht konfigurieren können).
Quellcode der Fabrik
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
};
Wenn Sie ein service()
it zurückgeben, geben Sie einer factory () ein function
, das das injiziert constructor
(geben Sie die Instanz des Konstruktors zurück, den Sie in Ihrem Service angegeben haben) und geben Sie es zurück
Quellcode des Dienstes
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
};
Im Grunde genommen erhalten Sie in beiden Fällen irgendwann einen Anbieter, der auf Ihre von Ihnen bereitgestellte Funktion eingestellt wird, aber Sie können alles andere als $ get angeben, wie Sie es ursprünglich in provider () für den Konfigurationsblock angegeben haben
Ich kenne viele ausgezeichnete Antworten, aber ich muss meine Erfahrungen mit der Verwendung von
1. service
für die meisten Fälle von Standard
2. teilen, factory
die zum Erstellen des Dienstes für diese bestimmte Instanz verwendet werden
// 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){ ...
}
}
})();
und mit:
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;
...
Etwas spät zur Party. Ich fand dies jedoch hilfreicher für diejenigen, die mehr über die Entwicklung von Angular JS Custom Services mithilfe von Factory-, Service- und Provider-Methoden erfahren möchten (oder Klarheit darüber haben möchten).
Ich bin auf dieses Video gestoßen, in dem die Methoden von Factory, Service und Provider für die Entwicklung von AngularJS Custom Services klar erläutert werden:
https://www.youtube.com/watch?v=oUXku28ex-M
Quellcode: http://www.techcbt.com/Post/353/Angular-JS-basics/how-to-develop-angularjs-custom-service
Der hier veröffentlichte Code wird direkt aus der oben genannten Quelle kopiert, um den Lesern zu helfen.
Der Code für den "werkseitigen" benutzerdefinierten Dienst lautet wie folgt (der sowohl für Synchronisierungs- als auch für Asynchronisierungsversionen zusammen mit dem Aufruf des http-Dienstes gilt):
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;
}
]);
Der Code für die "Service" -Methode für benutzerdefinierte Services (dies ist ziemlich ähnlich zu "Factory", unterscheidet sich jedoch vom Standpunkt der Syntax):
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");
});
};
}]);
Der Code für die "Provider" -Methode für benutzerdefinierte Dienste (dies ist erforderlich, wenn Sie einen Dienst entwickeln möchten, der konfiguriert werden kann):
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");
}]);
Schließlich die Benutzeroberfläche, die mit einem der oben genannten Dienste funktioniert:
<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>
Zur Verdeutlichung können Sie aus der AngularJS-Quelle sehen, dass ein Dienst nur die Factory-Funktion aufruft, die wiederum die Provider-Funktion aufruft:
function factory(name, factoryFn) {
return provider(name, { $get: factoryFn });
}
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Lassen Sie uns die drei Möglichkeiten des Umgangs mit Geschäftslogik in AngularJS auf einfache Weise diskutieren: ( Inspiriert von Yaakovs Coursera AngularJS-Kurs )
BEDIENUNG :
Syntax:
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>
Merkmale des Dienstes:
FABRIK
Schauen wir uns zunächst die Syntax an:
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;
}
Verwenden Sie nun die beiden oben genannten Elemente in der Steuerung:
var factoryOne = NameOfTheFactoryOne() //since it returns a function
factoryOne.someMethod();
var factoryTwo = NameOfTheFactoryTwo.getSomeService(); //accessing the object
factoryTwo.someMethod();
Merkmale der Fabrik:
.service()
Methode ist eine Factory , die immer dieselbe Art von Dienst erzeugt, nämlich einen Singleton, und ohne eine einfache Möglichkeit, das Verhalten zu konfigurieren. Diese .service()
Methode wird normalerweise als Verknüpfung für etwas verwendet, für das keinerlei Konfiguration erforderlich ist.ANBIETER
Schauen wir uns noch einmal zuerst die Syntax an:
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;
};
}
}
Funktionen des Anbieters:
.service
oder .factory
mehreren Methoden konfigurieren .$get
ist eine Funktion, die direkt an die Provider-Instanz angehängt ist. Diese Funktion ist eine Werksfunktion . Mit anderen Worten, es ist genau das, was wir verwenden, um die .factory
Methode bereitzustellen . In dieser Funktion erstellen wir unseren eigenen Service. Diese $get
Eigenschaft, das ist eine Funktion, macht den Anbieter zu einem Anbieter . AngularJS erwartet, dass der Anbieter über eine $ get-Eigenschaft verfügt, deren Wert eine Funktion ist, die Angular als Factory-Funktion behandelt. Das Besondere an diesem gesamten Provider-Setup ist jedoch die Tatsache, dass wir ein config
Objekt innerhalb des Service-Providers bereitstellen können. Dies ist normalerweise mit Standardeinstellungen verbunden, die wir später in dem Schritt überschreiben können, in dem wir die gesamte Anwendung konfigurieren können.Fabrik: Die Fabrik, in der Sie tatsächlich ein Objekt innerhalb der Fabrik erstellen und zurückgeben.
service: Der Service, für den Sie nur eine Standardfunktion haben, die das Schlüsselwort this verwendet, um die Funktion zu definieren.
Provider: Der Provider, für den Sie ein $ get definieren, kann verwendet werden, um das Objekt abzurufen, das die Daten zurückgibt.
Im Wesentlichen sind Anbieter, Fabrik und Service alle Services. Eine Factory ist ein Sonderfall eines Dienstes, bei dem Sie lediglich eine $ get () - Funktion benötigen, mit der Sie sie mit weniger Code schreiben können.
Die Hauptunterschiede zwischen Dienstleistungen, Fabriken und Anbietern sind ihre Komplexität. Services sind die einfachste Form, Fabriken sind etwas robuster und Provider können zur Laufzeit konfiguriert werden.
Hier ist eine Zusammenfassung, wann jeder verwendet werden soll:
Fabrik : Der von Ihnen angegebene Wert muss basierend auf anderen Daten berechnet werden.
Service : Sie geben ein Objekt mit Methoden zurück.
Anbieter : Sie möchten in der Konfigurationsphase das Objekt konfigurieren können, das vor seiner Erstellung erstellt werden soll. Verwenden Sie den Provider hauptsächlich in der App-Konfiguration, bevor die App vollständig initialisiert wurde.
1.Dienste sind Singleton-Objekte, die bei Bedarf erstellt und erst am Ende des Anwendungslebenszyklus (wenn der Browser geschlossen wird) bereinigt werden. Steuerungen werden zerstört und aufgeräumt, wenn sie nicht mehr benötigt werden.
2.Der einfachste Weg, einen Dienst zu erstellen, ist die Methode factory (). Mit der factory () -Methode können wir einen Service definieren, indem wir ein Objekt zurückgeben, das Servicefunktionen und Servicedaten enthält. In der Service-Definitionsfunktion platzieren wir unsere injizierbaren Services wie $ http und $ q. Ex:
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; });
Verwenden Sie die factory () in unserer App
Es ist einfach, die Fabrik in unserer Anwendung zu verwenden, da wir sie zur Laufzeit einfach dort injizieren können, wo wir sie benötigen.
angular.module('myApp')
.controller('MainController', function($scope, User) {
$scope.saveUser = User.save;
});
Syntaktischer Zucker ist der Unterschied . Es wird nur ein Anbieter benötigt. Oder mit anderen Worten, nur der Anbieter ist der reale Winkel, alle anderen werden abgeleitet (um den Code zu reduzieren). Es gibt auch eine einfache Version namens Value (), die nur den Wert, keine Berechnung oder Funktion zurückgibt. Gleichmäßiger Wert wird vom Anbieter abgeleitet!
Warum also solche Komplikationen, warum können wir nicht einfach den Anbieter verwenden und alles andere vergessen? Es soll uns helfen, Code einfach zu schreiben und besser zu kommunizieren. Und die Antwort wäre, je komplexer es wird, desto besser wird es sein, ein Framework zu verkaufen.
Die Winkelinjektion gibt uns den ersten Hinweis, um zu dieser Schlussfolgerung zu gelangen.
"$ injoror wird verwendet, um Objektinstanzen abzurufen, wie vom Anbieter definiert ", nicht Service, nicht Factory, sondern Provider.
Eine bessere Antwort wäre folgende: "Ein Angular-Service wird von einer Service-Factory erstellt. Diese Service-Fabriken sind Funktionen, die wiederum von einem Service-Provider erstellt werden. Die Service-Provider sind Konstruktorfunktionen. Wenn sie instanziiert werden, müssen sie eine Eigenschaft enthalten $ get genannt, das die Service Factory-Funktion enthält. "
Also Master Provider und Injektor und alles wird an seinen Platz fallen :). In Typescript wird es interessant, wenn $ get durch Erben von IServiceProvider in einem Anbieter implementiert werden kann.