Question Confus à propos de Service vs Factory


Si je comprends bien, quand à l'intérieur d'une usine, je retourne un objet qui est injecté dans un contrôleur. À l'intérieur d'un service, je traite de l'objet en utilisant this et ne rien retourner.

J'étais sous l'hypothèse qu'un service était toujours un singletonet qu'un nouvel objet d'usine est injecté dans chaque contrôleur. Cependant, comme il se trouve, un objet d'usine est un singleton aussi?

Exemple de code pour démontrer:

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

En changeant user.first dans ACtrl il se trouve que user.first dans BCtrl est également modifié, par ex. User est un singleton?

Ma supposition était qu'une nouvelle instance a été injectée dans un contrôleur avec une usine?


593
2017-12-07 11:31


origine


Réponses:


Tous les services angulaires sont des singletons:

Docs (voir Services comme singletons): https://docs.angularjs.org/guide/services

Enfin, il est important de réaliser que tous les services Angular sont des singletons d'application. Cela signifie qu'il n'y a qu'une seule instance d'un service donné par injecteur.

Fondamentalement, la différence entre le service et l'usine est la suivante:

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 + "!";
    }
  }
});

Consultez cette présentation sur $ provide: http://slides.wesalvaro.com/20121113/#/

Ces diapositives ont été utilisées dans l'une des rencontres AngularJs: http://blog.angularjs.org/2012/11/more-angularjs-meetup-videos.html


585
2017-12-07 13:17



Pour moi, la révélation est venue quand je me suis rendu compte qu'ils travaillent tous de la même façon: en faisant quelque chose une fois que, stockant la valeur qu'ils obtiennent, puis cracher cette même valeur stockée lorsqu'il est référencé via l'injection de dépendances.

Disons que nous avons:

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

La différence entre les trois est la suivante:

  1. ala valeur stockée vient de courir fn , en d'autres termes: fn()
  2. bLa valeur stockée vient de newing fn, en d'autres termes: new fn()
  3. cLa valeur stockée vient d'abord obtenir une instance par newing fn, puis en cours d'exécution d'un $get méthode de l'instance

ce qui signifie qu'il y a quelque chose comme un objet cache à l'intérieur de angular, dont la valeur de chaque injection n'est attribuée qu'une seule fois, quand ils ont été injectés la première fois, et où:

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

C'est pourquoi nous utilisons this dans les services, et définir un this.$get dans les fournisseurs.

J'espère que cela t'aides.


361
2017-11-14 06:32



exemple vivant

"Bonjour tout le monde" exemple

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

93
2017-10-28 13:50



Il y a aussi un moyen de retourner une fonction constructeur pour pouvoir retourner nouveau classes dans les usines, comme ceci:

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

Donc, vous pouvez le faire dans un contrôleur, qui utilise MyObjectWithParam:

var obj = new MyObjectWithParam("hello"),

Voir ici l'exemple complet:
http://plnkr.co/edit/GKnhIN?p=preview

Et voici les pages du groupe google, où il a été discuté:
https://groups.google.com/forum/#!msg/angular/56sdORWEoqg/b8hdPskxZXsJ 


57
2018-04-09 14:39



Voici les principales différences:

Prestations de service

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

Résultat: Lors de la déclaration de serviceName en tant qu'argument injectable, vous recevrez le instance d'une fonction transmis à module.service.

Utilisation: pourrait être utile pour partage des fonctions d'utilité qui sont utiles à invoquer en ajoutant simplement () à la référence de la fonction injectée. Peut aussi être exécuté avec injectedArg.call( this ) ou similaire.

Des usines

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

Résultat: Lorsque vous déclarez factoryName comme argument injectable, vous recevrez le valeur renvoyée en appelant la référence de fonction transmis à module.factory.

Utilisation: Peut être utile pour renvoyer un 'classe' fonction qui peut ensuite être nouveau pour créer des instances.

Vérifiez également Documentation AngularJS et une question similaire sur stackoverflow confus au sujet du service vs usine.

Voici exemple en utilisant les services et l'usine. En savoir plus sur Service AngularJS vs usine.


50
2017-12-23 00:01



Ajoutant à la première réponse, je pense que .service () est pour les gens qui ont écrit leur code dans un style orienté objet (C # / Java) (en utilisant ce mot-clé et instanciant l'objet via la fonction prototype / Constructeur).

L'usine est pour les développeurs qui écrivent du code qui est plus naturel au codage javascript / fonctionnel.

Jetez un oeil sur le code source de .service et la méthode .factory dans angular.js - en interne, ils appellent tous la méthode du fournisseur:

  function provider(name, provider_) {
    if (isFunction(provider_)) {
      provider_ = providerInjector.instantiate(provider_);
    }
    if (!provider_.$get) {
      throw Error('Provider ' + name + ' must define $get factory method.');
    }
    return providerCache[name + providerSuffix] = provider_;
  }

  function factory(name, factoryFn) { \
    return provider(name, { $get: factoryFn }); 
  }

  function service(name, constructor) {
    return factory(name, ['$injector', function($injector) {
      return $injector.instantiate(constructor);
    }]);
  }

27
2018-06-20 11:35



Très simplement:

.service - la fonction enregistrée sera appelée en tant que constructeur (alias 'newed')

.factory - la fonction enregistrée sera invoquée comme une fonction simple

Les deux sont invoqués une fois, ce qui crée un objet singleton qui est injecté dans d'autres composants de votre application.


25
2017-11-25 14:17



Tous les fournisseurs fonctionnent de la même manière. Les différentes méthodes service, factory, provider laissez-vous accomplir la même chose en moins de code.

P.S. Il y a aussi value et constant.

Chaque cas spécial en bas de la chaîne en commençant par provider et se terminant par value a une limitation supplémentaire. Donc, pour décider entre eux, vous devez vous demander ce que vous accomplissez ce que vous voulez avec moins de code.

Voici une photo qui vous montre ce que je veux dire:

enter image description here

Vous pouvez obtenir une ventilation et un guide de référence sur le blog, j'ai obtenu cette image de:

http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/


20
2017-12-10 13:02



Voici quelques exemples de services vs usines qui peuvent être utiles pour voir la différence entre eux. Fondamentalement, un service a appelé "nouveau ...", il est déjà instancié. Une usine n'est pas instanciée automatiquement.

Exemples de base

Renvoyer un objet de classe qui a une seule méthode

Voici un service qui a une seule méthode:

angular.service('Hello', function () {
  this.sayHello = function () { /* ... */ };
});

Voici une fabrique qui retourne un objet avec une méthode:

angular.factory('ClassFactory', function () {
  return {
    sayHello: function () { /* ... */ }
  };
});

Renvoie une valeur

Une usine qui renvoie une liste de nombres:

angular.factory('NumberListFactory', function () {
  return [1, 2, 3, 4, 5];
});

console.log(NumberListFactory);

Un service qui renvoie une liste de nombres:

angular.service('NumberLister', function () {
  this.numbers = [1, 2, 3, 4, 5];
});

console.log(NumberLister.numbers);

La sortie dans les deux cas est la même, la liste des nombres.

Exemples avancés

Variables "Class" utilisant des usines

Dans cet exemple, nous définissons un CounterFactory, il incrémente ou décrémente un compteur et vous pouvez obtenir le nombre actuel ou obtenir combien d'objets CounterFactory ont été créés:

angular.factory('CounterFactory', function () {
  var number_of_counter_factories = 0; // class variable

  return function () {
    var count = 0; // instance variable
    number_of_counter_factories += 1; // increment the class variable

    // this method accesses the class variable
    this.getNumberOfCounterFactories = function () {
      return number_of_counter_factories;
    };

    this.inc = function () {
      count += 1;
    };
    this.dec = function () {
      count -= 1;
    };
    this.getCount = function () {
      return count;
    };
  }

})

Nous utilisons le CounterFactory pour créer plusieurs compteurs. Nous pouvons accéder à la variable de la classe pour voir combien de compteurs ont été créés:

var people_counter;
var places_counter;

people_counter = new CounterFactory();
console.log('people', people_counter.getCount());
people_counter.inc();
console.log('people', people_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());

places_counter = new CounterFactory();
console.log('places', places_counter.getCount());

console.log('counters', people_counter.getNumberOfCounterFactories());
console.log('counters', places_counter.getNumberOfCounterFactories());

La sortie de ce code est:

people 0
people 1
counters 1
places 0
counters 2
counters 2

13
2017-07-29 07:56