web-dev-qa-db-fra.com

AngularJS: Quand utiliser le service au lieu de l'usine

S'il vous plaît supporter avec moi ici. Je sais qu'il existe d'autres réponses telles que: AngularJS: Service vs fournisseur vs usine

Cependant, je ne comprends toujours pas quand vous utiliserez le service par rapport à l'usine.

D'après ce que je peux dire, la fabrique est couramment utilisée pour créer des fonctions "communes" pouvant être appelées par plusieurs contrôleurs: Création de fonctions de contrôleur communes

Les documents Angular semblent préférer l’usine au service. Ils parlent même de "service" quand ils utilisent une usine qui est encore plus déroutante! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Quand utilisera-t-on le service?

Y at-il quelque chose qui est seulement possible ou beaucoup plus facile à faire avec le service?

Y a-t-il quelque chose de différent qui se passe dans les coulisses? Différences de performance/mémoire?

Voici un exemple. Autre que la méthode de déclaration, ils semblent identiques et je ne peux pas comprendre pourquoi je ferais l'un contre l'autre. http://jsfiddle.net/uEpkE/

Mise à jour: D'après la réponse de Thomas, cela semble impliquer que le service est destiné à une logique plus simple et une usine à une logique plus complexe avec des méthodes privées, j'ai donc mis à jour le code de violon ci-dessous et il semble que les deux sont capables de prendre en charge des fonctions privées?

myApp.factory('fooFactory', function() {
    var fooVar;
    var addHi = function(foo){ fooVar = 'Hi '+foo; }

    return {
        setFoobar: function(foo){
            addHi(foo);
        },
        getFoobar:function(){
            return fooVar;
        }
    };
});
myApp.service('fooService', function() {
    var fooVar;
    var addHi = function(foo){ fooVar = 'Hi '+foo;}

    this.setFoobar = function(foo){
        addHi(foo);
    }
    this.getFoobar = function(){
        return fooVar;
    }
});

function MyCtrl($scope, fooService, fooFactory) {
    fooFactory.setFoobar("fooFactory");
    fooService.setFoobar("fooService");
    //foobars = "Hi fooFactory, Hi fooService"
    $scope.foobars = [
        fooFactory.getFoobar(),
        fooService.getFoobar()
    ];
}
294
user1941747

Explication

Vous avez différentes choses ici:

D'abord:

  • Si vous utilisez un service, vous obtiendrez l'instance d'une fonction (mot-clé "this").
  • Si vous utilisez une fabrique, vous obtiendrez la valeur renvoyée en appelant la référence de la fonction (l'instruction de retour en usine).

ref: angular.service vs angular.factory

Seconde:

Gardez à l'esprit que tous les fournisseurs dans AngularJS (valeur, constante, services, usines) sont des singletons!

Troisième:

L'utilisation de l'un ou de l'autre (service ou usine) concerne le style de code. Mais, la manière courante dans AngularJS consiste à utiliser fabrique .

Pourquoi ?

Parce que "La méthode factory est le moyen le plus courant d’obtenir des objets dans le système d’injection de dépendance AngularJS. Elle est très flexible et peut contient une logique de création sophistiquée. Les fabriques étant des fonctions standard, nous pouvons également tirer parti d'une nouvelle portée lexicale pour simuler des variables "privées". Ceci est très utile car nous pouvons masquer les détails d'implémentation d'un service donné. "

( ref : http://www.Amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821 ).


Usage

Service: Peut être utile pour partager des fonctions utilitaires qu'il est utile d'invoquer en ajoutant simplement () à la référence de fonction injectée. Peut également être exécuté avec injectedArg.call(this) ou similaire.

Factory: Peut être utile pour renvoyer une fonction ‘class’ qui peut ensuite être créée pour créer des instances.

Donc, utilisez une fabrique lorsque vous avez une logique complexe dans votre service et vous ne voulez pas exposer cette complexité .

Dans les autres cas , si vous souhaitez renvoyer une instance d'un service, utilisez simplement le service .

Mais vous verrez avec le temps que vous utiliserez l’usine dans 80% des cas, je pense.

Pour plus de détails: http://blog.manishchhabra.com/2013/09/angularjs-service-vs-factory-with-example/


UPDATE:

Excellent post ici: http://iffycan.blogspot.com.ar/2013/05/angular-service-or-factory.html

"Si vous voulez que votre fonction soit appelée comme une fonction normale , utilisez . Si vous souhaitez que votre fonction soit instanciée avec le nouvel opérateur, utilisez service. Si vous ne connaissez pas la différence, utilisez usine. "


UPDATE:

L’équipe AngularJS fait son travail en donnant une explication: http://docs.angularjs.org/guide/providers

Et à partir de cette page:

"Factory et Service sont les recettes les plus couramment utilisées. La seule différence entre elles est que la recette de service fonctionne mieux pour les objets de type personnalisé, tandis que Factory peut générer des primitives et des fonctions JavaScript."

277
Thomas Pons

allernhwkim posté à l'origine ne réponse sur cette question avec un lien vers son blog , mais un modérateur l'a supprimée. C’est le seul message que j’ai trouvé qui ne dis pas simplement comment faire la même chose avec le service, le fournisseur et l’usine, mais aussi ce que vous pouvez faire avec un fournisseur que vous ne pouvez pas avec une usine et avec une usine que vous ne pouvez pas avec un service.

Directement depuis son blog:

app.service('CarService', function() {
   this.dealer="Bad";
    this.numCylinder = 4;
});

app.factory('CarFactory', function() {
    return function(numCylinder) {
      this.dealer="Bad";
        this.numCylinder = numCylinder
    };
});

app.provider('CarProvider', function() {
    this.dealerName = 'Bad';
    this.$get = function() {
        return function(numCylinder) {
            this.numCylinder = numCylinder;
            this.dealer = this.dealerName;
        }
    };
    this.setDealerName = function(str) {
      this.dealerName = str;
    }      
});

Cela montre comment CarService produira toujours une voiture à 4 cylindres, vous ne pouvez pas le changer pour des voitures individuelles. Tandis que CarFactory renvoie une fonction pour que vous puissiez faire new CarFactory dans votre contrôleur, en passant un certain nombre de cylindres spécifiques à cette voiture. Vous ne pouvez pas utiliser new CarService car CarService est un objet et non une fonction.

Les usines de raison ne fonctionnent pas comme ceci:

app.factory('CarFactory', function(numCylinder) {
      this.dealer="Bad";
      this.numCylinder = numCylinder
});

Et renvoyer automatiquement une fonction à instancier, c’est parce que vous ne pouvez pas le faire (ajouter des éléments au prototype/etc):

app.factory('CarFactory', function() {
    function Car(numCylinder) {
        this.dealer="Bad";
        this.numCylinder = numCylinder
    };
    Car.prototype.breakCylinder = function() {
        this.numCylinder -= 1;
    };
    return Car;
});

Voyez comment c'est littéralement une usine produisant une voiture.

La conclusion de son blog est plutôt bonne:

En conclusion,

---------------------------------------------------  
| Provider| Singleton| Instantiable | Configurable|
---------------------------------------------------  
| Factory | Yes      | Yes          | No          |
---------------------------------------------------  
| Service | Yes      | No           | No          |
---------------------------------------------------  
| Provider| Yes      | Yes          | Yes         |       
---------------------------------------------------  
  1. Utilisez Service lorsque vous avez besoin d’un objet simple, tel qu’un hachage, par exemple {foo; 1, bar: 2}. Il est facile de coder, mais vous ne pouvez pas l’instancier.

  2. Utilisez Factory lorsque vous devez instancier un objet, à savoir un nouveau client (), un nouveau commentaire (), etc.

  3. Utilisez Fournisseur lorsque vous devez le configurer. c'est-à-dire url de test, url QA, url de production.

Si vous constatez que vous ne faites que renvoyer un objet en usine, vous devez probablement utiliser le service.

Ne fais pas ça:

app.factory('CarFactory', function() {
    return {
        numCylinder: 4
    };
});

Utilisez le service à la place:

app.service('CarService', function() {
    this.numCylinder = 4;
});
109
Jonathan.

Le concept pour tous ces fournisseurs est beaucoup plus simple qu'il n'y parait. Si vous disséquez un fournisseur et retirez les différentes parties, cela devient très clair.

Pour le dire simplement, chacun de ces fournisseurs est une version spécialisée de l'autre, dans cet ordre: provider> factory> value/constant/service .

Si longtemps que le fournisseur fait ce que vous pouvez, vous pouvez utiliser le fournisseur plus loin dans la chaîne, ce qui réduira le code. Si cela ne donne pas ce que vous voulez, vous pouvez remonter la chaîne et il vous suffira d'écrire plus de code.

Cette image illustre ce que je veux dire. Dans cette image, vous verrez le code d'un fournisseur, les parties mises en surbrillance indiquant les parties de ce fournisseur pouvant être utilisées pour créer une fabrique, une valeur, etc.

Les fournisseurs AngularJS, les usines, les services, etc. sont tous identiques. Http://www.simplygoodcode.com/wp-content/uploads/2015/11/angularjs-provider-service-factory-highlight.png =

Pour plus de détails et d’exemples tirés du billet de blog sur lequel j’ai obtenu l’image, allez à: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory- in-angularjs /

19
Luis Perez

L'usine et le service résultent tous les deux en objets singleton pouvant être configurés par les fournisseurs, injectés dans des contrôleurs et exécutés en blocs. Du point de vue de l'injecté, il n'y a absolument aucune différence selon que l'objet provient d'une usine ou d'un service.

Alors, quand utiliser une usine et quand utiliser un service? Cela se résume à vos préférences de codage et à rien d’autre. Si vous aimez le modèle JS modulaire, optez pour l'usine. Si vous aimez le style de fonction constructeur ("classe"), optez pour le service. Notez que les deux styles prennent en charge les membres privés.

L’avantage du service est peut-être qu’il est plus intuitif du point de vue OOP: créez une "classe" et, en association avec un fournisseur, réutilisez le même code entre les modules et modifiez le comportement de les objets instanciés simplement en fournissant différents paramètres au constructeur dans un bloc de configuration.

8
Steve Lang

Même quand ils disent que tous les services et usines sont singleton, je ne suis pas tout à fait d'accord avec ça. Je dirais que les usines ne sont pas des singletons et c'est le but de ma réponse. Je pense vraiment au nom qui définit chaque composant (Service/Factory), je veux dire:

A factory car ce n’est pas un singleton, vous pouvez en créer autant que vous le souhaitez lorsque vous injectez, de sorte que cela fonctionne comme une fabrique d’objets. Vous pouvez créer une fabrique d'une entité de votre domaine et travailler plus confortablement avec ces objets qui pourraient ressembler à un objet de votre modèle. Lorsque vous récupérez plusieurs objets, vous pouvez les mapper dans cet objet et il peut agir comme un autre calque entre le modèle DDBB et le modèle AngularJs. Vous pouvez ajouter des méthodes aux objets pour orienter un peu plus les objets de votre application AngularJs.

Pendant ce temps un service est un singleton, nous ne pouvons donc créer qu’un seul type, peut-être pas mais nous n’avons qu’une seule instance lorsque nous injectons dans un contrôleur, ainsi un service fournit plus comme un service commun ( autres appels, fonctionnalité ..) aux contrôleurs.

Conceptuellement, vous pouvez penser comme les services fournissent un service, les fabriques peuvent créer plusieurs instances (objets) d'une classe.

Il n'y a rien qu'une Usine ne puisse faire ou fait mieux par rapport à un Service. Et vice versa. L'usine semble être plus populaire. La raison en est qu'il est commode de manipuler des membres privés/publics. Le service serait plus maladroit à cet égard. Lorsque vous codez un service, vous avez tendance à rendre les membres de votre objet publics via le mot clé "this" et vous pouvez soudainement découvrir que ces membres publics ne sont pas visibles par les méthodes privées (c'est-à-dire les fonctions internes).

var Service = function(){

  //public
  this.age = 13;

  //private
  function getAge(){

    return this.age; //private does not see public

  }

  console.log("age: " + getAge());

};

var s = new Service(); //prints 'age: undefined'

Angular utilise le mot-clé "new" pour créer un service, de sorte que l'instance Angular transmise au contrôleur aura le même inconvénient. Bien sûr, vous pouvez résoudre le problème en utilisant ceci/cela:

var Service = function(){

  var that = this;

  //public
  this.age = 13;

  //private
  function getAge(){

    return that.age;

  }

  console.log("age: " + getAge());

};

var s = new Service();// prints 'age: 13'  

Mais avec une constante de service importante, cela rendrait le code peu lisible. De plus, les prototypes de service ne verront pas de membres privés. Seul le public sera disponible pour eux:

var Service = function(){

  var name = "George";

};

Service.prototype.getName = function(){

  return this.name; //will not see a private member

};

var s = new Service();
console.log("name: " + s.getName());//prints 'name: undefined'

En résumé, utiliser Factory est plus pratique. Comme l’usine n’a pas ces inconvénients. Je recommanderais de l'utiliser par défaut.

2
Andrew Krook

Services

Syntaxe: module.service ('serviceName', fonction); Résultat: Lors de la déclaration de serviceName en tant qu'argument injectable, la référence de fonction actuelle transmise à module.service sera fournie.

sage: Peut être utile pour partager des fonctions utilitaires qu'il est utile d'invoquer en ajoutant simplement () à la référence de fonction injectée. Peut également être exécuté avec injectedArg.call (this) ou similaire.

sines

Syntaxe: module.factory ('nom_usine', fonction);

Résultat: Lors de la déclaration de factoryName en tant qu'argument injectable, la valeur renvoyée par la référence de la fonction transmise à module.factory sera fournie.

sage: Peut être utile pour renvoyer une fonction 'classe' pouvant ensuite être créée pour créer des instances.

Fournisseurs

Syntaxe: module.provider ('nom du fournisseur', fonction);

Résultat: Lors de la déclaration de providerName en tant qu'argument injectable, vous recevrez la valeur renvoyée en appelant la méthode $ get de la référence de fonction transmise à module.provider.

sage: Peut être utile pour renvoyer une fonction 'classe' qui peut ensuite être créée pour créer des instances, mais qui nécessite une sorte de configuration avant d'être injectée. Peut-être utile pour les classes réutilisables dans plusieurs projets? Encore un peu flou sur celui-ci.

0
Nishant Upadhyay

L'usine et le service sont la méthode la plus couramment utilisée. La seule différence entre eux est que la méthode Service fonctionne mieux pour les objets nécessitant une hiérarchie d'héritage, tandis que la fabrique peut produire des primitives et des fonctions JavaScript.

La fonction de fournisseur est la méthode principale et toutes les autres ne sont que du sucre syntaxique. Vous n'en avez besoin que si vous construisez un élément de code réutilisable nécessitant une configuration globale.

Il existe cinq méthodes pour créer des services: Valeur, Usine, Service, Fournisseur et Constante. Vous pouvez en apprendre plus à ce sujet ici service angulaire , cet article explique toutes ces méthodes à l'aide d'exemples de démonstration pratiques.

.

0
user3114005

Peut utiliser les deux comme vous le souhaitez: soit créer un objet ou j st pour accéder aux fonctions des deux


Vous pouvez créer un nouvel objet à partir du service

app.service('carservice', function() {
    this.model = function(){
        this.name = Math.random(22222);
        this.price = 1000;
        this.colour = 'green';
        this.manufacturer = 'bmw';
    }
});

.controller('carcontroller', function ($scope,carservice) { 
    $scope = new carservice.model();
})

Remarque :

  • service par défaut retourne objet et non fonction constructeur.
  • C'est pourquoi la fonction constructeur est définie sur la propriété this.model.
  • En raison de ce service retournera objet, mais mais à l'intérieur de cet objet sera une fonction constructeur qui sera utilisée pour créer un nouvel objet;

Vous pouvez créer un nouvel objet à partir de l'usine

app.factory('carfactory', function() {
    var model = function(){
        this.name = Math.random(22222);
        this.price = 1000;
        this.colour = 'green';
        this.manufacturer = 'bmw';
    }
    return model;
});

.controller('carcontroller', function ($scope,carfactory) { 
    $scope = new carfactory();
})

Remarque :

  • factory par défaut retourne une fonction constructeur et non un objet.
  • C'est pourquoi le nouvel objet peut être créé avec la fonction constructeur.

Créer un service pour simplement accéder à des fonctions simples

app.service('carservice', function () {
   this.createCar = function () {
       console.log('createCar');
   };
   this.deleteCar = function () {
       console.log('deleteCar');
   };
});

.controller('MyService', function ($scope,carservice) { 
    carservice.createCar()
})

Créer une usine pour accéder simplement à des fonctions simples

app.factory('carfactory', function () {
    var obj = {} 
        obj.createCar = function () {
            console.log('createCar');
        };
       obj.deleteCar = function () {
       console.log('deleteCar');
    };
});

.controller('MyService', function ($scope,carfactory) { 
    carfactory.createCar()
})

Conclusion :

  • vous pouvez utiliser les deux comme vous le souhaitez pour créer un nouvel objet ou simplement pour accéder à des fonctions simples
  • Il n'y aura pas de perte de performance, en utilisant l'un sur l'autre
  • Les deux sont des objets singleton et une seule instance est créée par application.
  • Étant une seule instance partout où leur référence est passée.
  • Dans angular documentation l’usine est appelée service et aussi le service est appelé service.
0
vijay