C'est ce qui m'a aidé à comprendre la différence, grâce à un article de blog de Pascal Precht.
Un service est une méthode sur un module qui prend un nom et une fonction qui définit le service. Vous pouvez injecter et utiliser ce service particulier dans d'autres composants, comme les contrôleurs, les directives et les filtres. Une usine est une méthode sur un module et elle prend également un nom et une fonction, qui définit l'usine. Nous pouvons également injecter et utiliser de la même manière que nous l'avons fait avec le service.
Les objets créés avec new utilisent la valeur de la propriété prototype de leur fonction constructeur comme prototype, j'ai donc trouvé le code angulaire qui appelle Object.create (), qui, selon moi, est la fonction constructeur de service lorsqu'elle est instanciée. Cependant, une fonction d'usine n'est en réalité qu'une fonction qui est appelée, c'est pourquoi nous devons renvoyer un objet littéral pour l'usine.
Voici le code angulaire 1.5 que j'ai trouvé en usine:
var needsRecurse = false;
var destination = copyType(source);
if (destination === undefined) {
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source));
needsRecurse = true;
}
Extrait de code source angulaire pour la fonction factory ():
function factory(name, factoryFn, enforce) {
return provider(name, {
$get: enforce !== false ? enforceReturnValue(name, factoryFn) : factoryFn
});
}
Il prend le nom et la fonction d'usine qui sont passés et retourne un fournisseur avec le même nom, qui a une méthode $ get qui est notre fonction d'usine. Chaque fois que vous demandez à l'injecteur une dépendance spécifique, il demande essentiellement au fournisseur correspondant une instance de ce service, en appelant la méthode $ get (). C'est pourquoi $ get () est requis lors de la création de fournisseurs.
Voici le code angulaire 1.5 pour le service.
function service(name, constructor) {
return factory(name, ['$injector', function($injector) {
return $injector.instantiate(constructor);
}]);
}
Il s'avère que lorsque nous appelons service (), il appelle en fait factory ()! Cependant, il ne transmet pas simplement notre fonction de constructeur de services à l'usine telle quelle. Il transmet également une fonction qui demande à l'injecteur d'instancier un objet par le constructeur donné.
En d'autres termes, si nous injectons MyService quelque part, ce qui se passe dans le code est:
MyServiceProvider.$get(); // return the instance of the service
Pour le reformuler, un service appelle une fabrique, qui est une méthode $ get () sur le fournisseur correspondant. De plus, $ injector.instantiate () est la méthode qui appelle finalement Object.create () avec la fonction constructeur. C'est pourquoi nous utilisons "ceci" dans les services.
Pour ES5, peu importe ce que nous utilisons: service () ou usine (), c'est toujours une usine appelée qui crée un fournisseur pour notre service.
Vous pouvez également faire exactement la même chose avec les services. Un service est une fonction constructeur, cependant, qui ne nous empêche pas de renvoyer des littéraux d'objet. Nous pouvons donc prendre notre code de service et l'écrire de manière à ce qu'il fasse exactement la même chose que notre usine ou en d'autres termes, vous pouvez écrire un service en tant qu'usine pour retourner un objet.
Pourquoi la plupart des gens recommandent-ils d'utiliser les usines plutôt que les services? C'est la meilleure réponse que j'ai vue qui vient du livre de Pawel Kozlowski: Mastering Web Application Development with AngularJS.
La méthode d'usine est le moyen le plus courant d'intégrer des objets dans le système d'injection de dépendance AngularJS. Il 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 profiter 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é. "