AngularJS indique clairement dans sa documentation que les services sont des singletons:
AngularJS services are singletons
Contre-intuitivement, module.factory
retourne également une instance Singleton.
Étant donné qu'il existe de nombreux cas d'utilisation pour les services non singleton, quelle est la meilleure façon d'implémenter la méthode de fabrique pour renvoyer des instances d'un service, de sorte que chaque fois qu'une ExampleService
dépendance est déclarée, elle soit satisfaite par une instance différente de ExampleService
?
Réponses:
Je ne pense pas que nous devrions jamais avoir une
new
fonction capable de retourner une usine car cela commence à décomposer l'injection de dépendances et la bibliothèque se comportera de manière maladroite, en particulier pour les tiers. En bref, je ne suis pas sûr qu'il existe des cas d'utilisation légitimes pour les services non singleton.Une meilleure façon d'accomplir la même chose est d'utiliser la fabrique comme API pour renvoyer une collection d'objets avec des méthodes getter et setter qui leur sont attachées. Voici un pseudo-code montrant comment l'utilisation de ce type de service peut fonctionner:
Il ne s'agit que d'un pseudo-code pour rechercher un widget par ID, puis pour pouvoir enregistrer les modifications apportées à l'enregistrement.
Voici un pseudo-code pour le service:
Bien que non inclus dans cet exemple, ces types de services flexibles pourraient également facilement gérer l'état.
Je n'ai pas le temps pour le moment, mais si cela peut être utile, je peux préparer un simple Plunker plus tard pour en faire la démonstration.
la source
$resource
.Je ne suis pas tout à fait sûr du cas d'utilisation que vous essayez de satisfaire. Mais il est possible d'avoir une instance de retour d'usine d'un objet. Vous devriez pouvoir le modifier en fonction de vos besoins.
JsFiddle
Actualisé
Considérez la demande suivante pour les services non singleton . Dans lequel Brian Ford note:
et son exemple de retour des instances des usines:
Je dirais également que son exemple est supérieur en raison du fait que vous n'avez pas à utiliser le
new
mot - clé dans votre contrôleur. Il est encapsulé dans lagetInstance
méthode du service.la source
ngInfiniteScroll
et un service de recherche personnalisé afin de pouvoir retarder l'initialisation jusqu'à un événement de clic. JSFiddle de la première réponse mis à jour avec la deuxième solution: jsfiddle.net/gavinfoley/G5ku5new
est déclarative et il est facile de dire tout de suite quels services sont des singletons et ce qui ne le sont pas. Basé sur si un objet est en cours de création.Une autre méthode consiste à copier l'objet de service avec
angular.extend()
.puis, par exemple, dans votre contrôleur
Voici un plunk .
la source
Je sais que ce message a déjà reçu une réponse, mais je pense toujours qu'il y aurait des scénarios légitimes dont vous auriez besoin pour avoir un service non singleton. Disons qu'il existe une logique métier réutilisable qui peut être partagée entre plusieurs contrôleurs. Dans ce scénario, le meilleur endroit pour placer la logique serait un service, mais que se passe-t-il si nous devons conserver un état dans notre logique réutilisable? Ensuite, nous avons besoin d'un service non singleton afin de pouvoir être partagé entre différents contrôleurs dans l'application. Voici comment j'implémenterais ces services:
la source
Voici mon exemple de service non singleton, il provient d'un ORM sur lequel je travaille. Dans l'exemple, je montre un modèle de base (ModelFactory) dont je veux que les services ('utilisateurs', 'documents') héritent et étendent potentiellement.
Dans mon ORM, ModelFactory injecte d'autres services pour fournir des fonctionnalités supplémentaires (requête, persistance, mappage de schéma) qui sont mises en bac à sable à l'aide du système de modules.
Dans l'exemple, le service utilisateur et le service de documents ont les mêmes fonctionnalités mais ont leurs propres étendues indépendantes.
la source
angular ne donne qu'une option de service / usine unique . une façon de contourner le problème est d'avoir un service d'usine qui créera une nouvelle instance pour vous à l'intérieur de votre contrôleur ou d'autres instances de consommateur. la seule chose qui est injectée est la classe qui crée de nouvelles instances. c'est un bon endroit pour injecter d'autres dépendances ou pour initialiser votre nouvel objet aux spécifications de l'utilisateur (ajout de services ou de configuration)
Ensuite, dans votre instance consommateur, vous avez besoin du service d'usine et appelez la méthode de construction sur l'usine pour obtenir une nouvelle instance lorsque vous en avez besoin
vous pouvez voir qu'il offre l'opportunité d'injecter des services spécifiques qui ne sont pas disponibles dans l'étape d'usine. vous pouvez toujours avoir une injection sur l'instance de fabrique à utiliser par toutes les instances de modèle.
Notez que j'ai dû supprimer du code pour que je puisse faire des erreurs de contexte ... si vous avez besoin d'un exemple de code qui fonctionne, faites-le moi savoir.
Je crois que NG2 aura la possibilité d'injecter une nouvelle instance de votre service au bon endroit dans votre DOM afin que vous n'ayez pas besoin de créer votre propre implémentation d'usine. devra attendre et voir :)
la source
Je pense qu'il y a de bonnes raisons de créer une nouvelle instance d'un objet dans un service. Nous devrions également garder l'esprit ouvert plutôt que de simplement dire que nous ne devrions jamais faire une telle chose, mais le singleton a été conçu de cette façon pour une raison . Les contrôleurs sont souvent créés et détruits au cours du cycle de vie de l'application, mais les services doivent être persistants.
Je peux penser à un cas d'utilisation dans lequel vous avez un flux de travail quelconque, comme l'acceptation d'un paiement et vous avez plusieurs propriétés définies, mais vous devez maintenant changer leur type de paiement car la carte de crédit du client a échoué et il doit fournir une forme différente de Paiement. Bien sûr, cela a beaucoup à voir avec la façon dont vous créez votre application. Vous pouvez réinitialiser toutes les propriétés de l'objet de paiement ou créer une nouvelle instance d'un objet dans le service . Mais vous ne voudriez pas d'une nouvelle instance du service, ni ne voudriez actualiser la page.
Je pense qu'une solution fournit un objet dans le service que vous pouvez créer et définir une nouvelle instance. Mais, pour être clair, l'instance unique du service est importante car un contrôleur peut être créé et détruit plusieurs fois, mais les services ont besoin de persistance. Ce que vous recherchez n'est peut-être pas une méthode directe dans Angular, mais un modèle d'objet que vous pouvez gérer dans votre service.
À titre d'exemple, j'ai fait un bouton de réinitialisation . (Ce n'est pas testé, c'est vraiment juste une idée rapide d'un cas d'utilisation pour créer un nouvel objet dans un service.
la source
Voici une autre approche du problème dont j'étais assez satisfait, en particulier lorsqu'elle est utilisée en combinaison avec Closure Compiler avec les optimisations avancées activées:
la source