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

S’il vous plaît supportez avec moi ici. Je sais qu’il y a d’autres réponses telles que: AngularJS: Service vs fournisseur vs usine

Cependant, je n’arrive toujours pas à comprendre quand vous utiliseriez le service après-vente.

D’après ce que je peux dire, l’usine 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 Angular Docs semblent préférer le service d’usine. Ils font même référence au “service” lorsqu’ils utilisent l’usine, ce qui est encore plus déroutant! http://docs.angularjs.org/guide/dev_guide.services.creating_services

Alors, quand utiliserait-on le service?

Y a-t-il quelque chose qui est seulement possible ou beaucoup plus facile 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, le service semble simplifier la logique et l’usine pour une logique plus complexe avec des méthodes privées. J’ai donc mis à jour le code ci-dessous.

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

Explication

Vous avez différentes choses ici:

Premier:

  • 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 (la déclaration de retour en usine).

ref: angular.service vs angular.factory

Seconde:

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

Troisième:

L’utilisation de l’un ou l’autre (service ou usine) concerne le style de code. Mais la manière la plus courante à AngularJS est d’utiliser l’ usine .

Pourquoi ?

Parce que “la méthode usine est la manière la plus courante d’obtenir des objects dans le système d’dependency injections AngularJS. Elle est très flexible et peut contenir une logique de création sophistiquée. Les usines étant des fonctions régulières, nous pouvons également “variables. Ceci est très utile car nous pouvons masquer les détails d’implémentation d’un service donné.”

( réf : http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821 ).


Usage

Service: Peut être utile pour partager des fonctions utilitaires utiles à 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 de classe qui peut ensuite être utilisée pour créer des instances.

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

Dans d’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/


METTRE À JOUR :

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

“Si vous souhaitez que votre fonction soit appelée comme une fonction normale , utilisez factory . 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 factory.”


METTRE À JOUR :

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

Et de cette page:

“Factory et Service sont les recettes les plus utilisées. La seule différence entre elles est que la recette de service fonctionne mieux pour les objects de type personnalisé, tandis que Factory peut produire des primitives et des fonctions JavaScript.”

allernhwkim a initialement publié une réponse sur cette question en lien avec son blog , cependant un modérateur l’a supprimé. C’est le seul article que j’ai trouvé qui ne vous dit pas seulement comment faire la même chose avec le service, le fournisseur et l’usine, mais vous indique également ce que vous pouvez faire avec un fournisseur que vous ne pouvez pas avec une usine. une usine que vous ne pouvez pas avec un service.

Directement de 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 le CarService produira toujours une voiture avec 4 cylindres, vous ne pouvez pas le changer pour des voitures individuelles. Alors que CarFactory retourne une fonction pour que vous puissiez faire de new CarFactory dans votre contrôleur, en transmettant un certain nombre de cylindres spécifiques à cette voiture. Vous ne pouvez pas faire de new CarService car CarService est un object et non une fonction.

La raison pour laquelle les usines ne fonctionnent pas comme ceci:

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

Et renvoyer automatiquement une fonction pour que vous instanciez, c’est parce que vous ne pouvez pas le faire (append 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 comme c’est littéralement une usine qui produit 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 n’avez besoin que d’un simple object tel qu’un Hash, par exemple {foo; 1, bar: 2}. Il est facile de coder, mais vous ne pouvez pas l’instancier.

  2. Utilisez Factory lorsque vous avez besoin d’instancier un object, par exemple new Customer (), new Comment (), etc.

  3. Utilisez le fournisseur lorsque vous devez le configurer. c’est-à-dire l’url de test, l’url QA, l’URL de production.

Si vous ne faites que retourner un object en usine, vous devriez 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; }); 

Le concept pour tous ces fournisseurs est beaucoup plus simple qu’il n’apparaît au départ. 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 .

Tant que le fournisseur fait ce que vous pouvez, vous pouvez utiliser le fournisseur plus bas de la chaîne, ce qui entraînerait moins de code. Si cela n’atteint pas ce que vous voulez, vous pouvez monter la chaîne et vous devrez simplement écrire plus de code.

Cette image illustre ce que je veux dire, dans cette image, vous verrez le code pour un fournisseur, avec les parties en surbrillance vous montrant quelles parties du fournisseur pourraient être utilisées pour créer une usine, une valeur, etc. à la place.

Les fournisseurs AngularJS, les usines, les services, etc. sont tous la même chose http://soffr.miximages.com/angularjs/angularjs-provider-service-factory-highlight.png

Pour plus de détails et d’exemples tirés de l’article de blog sur lequel je reçois l’image, rendez-vous sur: http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/

La fabrique et le service génèrent des objects singleton pouvant être configurés par les fournisseurs et injectés dans les contrôleurs et les blocs d’exécution. Du sharepoint vue de l’injecté, il n’y a absolument aucune différence que l’object vienne d’une usine ou d’un service.

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

L’avantage du service peut être qu’il est plus intuitif du sharepoint vue de la POO: créer une “classe” et, conjointement avec un fournisseur, réutiliser le même code entre les modules et varier le comportement des objects instanciés en fournissant simplement parameters différents au constructeur dans un bloc de configuration.

Il n’y a rien qu’une usine ne peut faire ou faire mieux qu’un service. Et vice versa. Factory semble être plus populaire. La raison en est sa commodité dans le traitement des membres privés / publics. Le service serait plus maladroit à cet égard. Lors du codage d’un service, vous avez tendance à rendre publics les membres de votre object via «ce» mot-clé et à découvrir que ces membres publics ne sont pas visibles par les méthodes privées (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 pour vous, de sorte que l’instance Angular transmise au contrôleur aura le même inconvénient. Bien sûr, vous pouvez surmonter 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 mal lisible. De plus, les prototypes de service ne verront pas de membres privés – seul le public sera à leur disposition:

 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 Factory n’a pas ces inconvénients. Je recommanderais de l’utiliser par défaut.

Même quand ils disent que tous les services et les usines sont des singleton, je ne suis pas d’accord à 100% avec cela. 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:

Une fabrique car ce n’est pas un singleton, vous pouvez en créer autant que vous voulez quand vous l’injectez, cela fonctionne donc comme une fabrique d’objects. Vous pouvez créer une fabrique d’une entité de votre domaine et travailler plus confortablement avec ces objects, qui pourraient être comme un object de votre modèle. Lorsque vous récupérez plusieurs objects, vous pouvez les mapper dans ces objects et agir comme un autre calque entre le modèle DDBB et le modèle AngularJs. Vous pouvez append des méthodes aux objects afin de les orienter un peu plus vers votre application AngularJs.

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

Conceptuellement, vous pouvez penser que les services offrent un service, les usines peuvent créer plusieurs instances (objects) d’une classe

Prestations de service

Syntaxe : module.service (‘serviceName’, fonction); Résultat : lorsque vous déclarez serviceName comme argument injectable, vous recevrez la référence de fonction réelle transmise à module.service.

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

Des usines

Syntaxe : module.factory (‘factoryName’, fonction);

Résultat : lorsque vous déclarez factoryName en tant qu’argument injectable, vous recevez la valeur renvoyée en appelant la référence de fonction transmise à module.factory.

Utilisation : Peut être utile pour renvoyer une fonction de classe qui peut ensuite être créée pour créer des instances.

Fournisseurs

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

Résultat : lorsque vous déclarez providerName comme argument injectable, vous recevez la valeur renvoyée en appelant la méthode $ get de la référence de fonction transmise à module.provider.

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

Peut utiliser les deux comme vous le souhaitez : que ce soit pour créer un object ou pour accéder aux fonctions des deux


Vous pouvez créer un nouvel object à 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 renvoie l’object et non la fonction constructeur.
  • C’est pourquoi la fonction constructeur est définie sur la propriété this.model.
  • En raison de ce service retournera object, mais mais à l’intérieur de cet object sera la fonction constructeur qui sera utilisée pour créer un nouvel object;

Vous pouvez créer un nouvel object depuis 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 renvoie la fonction constructeur et non l’object.
  • C’est pourquoi un nouvel object peut être créé avec la fonction constructeur.

Créer un service pour 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 fabrique pour accéder à 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 à la fois la manière dont vous voulez créer un nouvel object ou accéder à des fonctions simples
  • Il n’y aura aucun impact sur la performance, en utilisant l’un sur l’autre
  • Les deux sont des objects singleton et une seule instance est créée par application.
  • N’étant qu’une instance chaque fois que leur référence est passée.
  • Dans la documentation angular, l’ usine s’appelle le service et le service est appelé service .