631 Stimmen

Verwirrt über Service vs. Fabrik

So wie ich es verstehe, gebe ich innerhalb einer Fabrik ein Objekt zurück, das in einen Controller injiziert wird. Wenn ich mich in einem Dienst befinde, behandle ich das Objekt mit this und nichts zurückgeben.

Ich bin davon ausgegangen, dass ein Dienst immer ein Singleton und dass ein neues Fabrikobjekt wird in jeden Controller injiziert. Doch wie sich herausstellt, ist ein Fabrikobjekt auch ein Singleton?

Beispielcode zur Demonstration:

var factories = angular.module('app.factories', []);
var app = angular.module('app',  ['ngResource', 'app.factories']);

factories.factory('User', function () {
  return {
    first: 'John',
    last: 'Doe'
  };
});

app.controller('ACtrl', function($scope, User) {
  $scope.user = User;
});

app.controller('BCtrl', function($scope, User) {
  $scope.user = User;
});

Beim Wechsel user.first en ACtrl es stellt sich heraus, dass user.first en BCtrl wird ebenfalls geändert, z. B. User ein Singleton ist?

Meine Annahme war, dass eine neue Instanz in einem Controller mit einer Fabrik injiziert wurde?

605voto

matys84pl Punkte 8344

Alle Winkeldienste sind Singletons :

Docs (siehe Dienstleistungen als Einzeldienstleistungen ): https://docs.angularjs.org/guide/services

Schließlich ist es wichtig zu wissen, dass alle Angular-Dienste Anwendungssingletons sind. Das bedeutet, dass es nur eine Instanz eines bestimmten Dienstes pro Injektor gibt.

Der Unterschied zwischen dem Service und dem Werk ist im Wesentlichen der folgende:

app.service('myService', function() {

  // service is just a constructor function
  // that will be called with 'new'

  this.sayHello = function(name) {
     return "Hi " + name + "!";
  };
});

app.factory('myFactory', function() {

  // factory returns an object
  // you can run some code before

  return {
    sayHello : function(name) {
      return "Hi " + name + "!";
    }
  }
});

Sehen Sie sich diese Präsentation über $provide an: http://slides.wesalvaro.com/20121113/#/

Diese Folien wurden bei einem der AngularJs-Meetings verwendet: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html

389voto

Lucia Punkte 11999

Für mich war es eine Offenbarung, als ich feststellte, dass sie alle auf dieselbe Weise funktionieren: indem sie etwas ausführen einmal und speichern den Wert, den sie erhalten, und zahlen dann denselben gespeicherten Wert wenn durch Dependency Injection referenziert wird.

Sagen wir, wir haben:

app.factory('a', fn);
app.service('b', fn);
app.provider('c', fn);

Der Unterschied zwischen den drei ist, dass:

  1. a Der gespeicherte Wert stammt aus der Ausführung fn mit anderen Worten: fn()
  2. b Der gespeicherte Wert kommt von new ing fn mit anderen Worten: new fn()
  3. c Der gespeicherte Wert kommt vom ersten Abruf einer Instanz von new ing fn und dann eine $get Methode der Instanz

das heißt, es gibt so etwas wie ein Cache-Objekt innerhalb von Angular, dessen Wert jeder Injektion nur einmal zugewiesen wird, wenn sie das erste Mal injiziert wurde, und wo:

cache.a = fn()
cache.b = new fn()
cache.c = (new fn()).$get()

Aus diesem Grund verwenden wir this in Dienstleistungen, und definieren Sie eine this.$get bei den Anbietern.

95voto

EpokK Punkte 37908

Live-Beispiel

Beispiel "Hallo Welt"

mit 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() {
    // In the provider function, you cannot inject any
    // service or factory. This can only be done at the
    // "$get" method.

    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()];
}

57voto

JustGoscha Punkte 23915

Es gibt auch eine Möglichkeit, eine Konstruktorfunktion zurückzugeben, so dass Sie Folgendes zurückgeben können newable Klassen in Fabriken, etwa so:

function MyObjectWithParam($rootScope, name) {
  this.$rootScope = $rootScope;
  this.name = name;
}
MyObjectWithParam.prototype.getText = function () {
  return this.name;
};

App.factory('MyObjectWithParam', function ($injector) {
  return function(name) { 
    return $injector.instantiate(MyObjectWithParam,{ name: name });
  };
}); 

Sie können dies also in einem Controller tun, der MyObjectWithParam verwendet:

var obj = new MyObjectWithParam("hello"),

Sehen Sie hier das vollständige Beispiel:
http://plnkr.co/edit/GKnhIN?p=preview

Und hier die Seiten der Google-Gruppe, in der das Thema diskutiert wurde:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ

51voto

Manish Chhabra Punkte 3015

Hier sind die wichtigsten Unterschiede:

Dienstleistungen

Syntax: module.service( 'serviceName', function );

Ergebnis: Wenn Sie serviceName als injizierbares Argument deklarieren, erhalten Sie die Instanz einer Funktion übergeben an module.service .

Verwendung: Könnte nützlich sein für Gemeinsame Nutzenfunktionen die durch einfaches Anhängen von () an die injizierte Funktionsreferenz aufgerufen werden können. Kann auch ausgeführt werden mit injectedArg.call( this ) oder ähnlich.

Fabriken

Syntax: module.factory( 'factoryName', function );

Ergebnis: Wenn Sie factoryName als injizierbares Argument deklarieren, erhalten Sie die Wert, der durch den Aufruf der Funktionsreferenz zurückgegeben wird übergeben an module.factory .

Verwendung: Könnte nützlich sein für die Rückgabe einer Klasse Funktion, die dann neu erstellt werden kann, um Instanzen zu erzeugen.

Prüfen Sie auch AngularJS-Dokumentation und ähnliche Frage auf Stackoverflow verwirrt über Service vs. Fabrik .

Hier ist Beispiel mit Dienstleistungen und Fabrik . Lesen Sie mehr über AngularJS-Dienst vs. Fabrik .

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X