AngularJS establece claramente en su documentación que los servicios son Singletons:
AngularJS services are singletons
Contrariamente a la intuición, module.factory
también devuelve una instancia de Singleton.
Dado que hay muchos casos de uso para servicios que no son singleton, ¿cuál es la mejor manera de implementar el método de fábrica para devolver instancias de un servicio, de modo que cada vez que ExampleService
se declare una dependencia, se satisfaga con una instancia diferente de ExampleService
?
Respuestas:
No creo que nunca deberíamos tener una fábrica que devuelva una
new
función capaz, ya que esto comienza a romper la inyección de dependencia y la biblioteca se comportará de manera incómoda, especialmente para terceros. En resumen, no estoy seguro de que existan casos de uso legítimos para servicios que no sean singleton.Una mejor manera de lograr lo mismo es usar la fábrica como API para devolver una colección de objetos con métodos getter y setter adjuntos. Aquí hay un pseudocódigo que muestra cómo podría funcionar el uso de ese tipo de servicio:
Esto es solo un pseudocódigo para buscar un widget por ID y luego poder guardar los cambios realizados en el registro.
Aquí hay un pseudocódigo para el servicio:
Aunque no se incluyen en este ejemplo, estos tipos de servicios flexibles también podrían administrar fácilmente el estado.
No tengo tiempo en este momento, pero si es útil, puedo armar un Plunker simple más tarde para demostrarlo.
fuente
$resource
.No estoy completamente seguro de qué caso de uso está tratando de satisfacer. Pero es posible tener instancias de retorno de fábrica de un objeto. Debería poder modificar esto para adaptarlo a sus necesidades.
JsFiddle
Actualizado
Considere la siguiente solicitud para servicios que no son singleton . En el que Brian Ford señala:
y su ejemplo de casos que regresan de las fábricas:
También diría que su ejemplo es superior debido al hecho de que no tiene que usar la
new
palabra clave en su controlador. Está encapsulado dentro delgetInstance
método del servicio.fuente
ngInfiniteScroll
un servicio de búsqueda personalizado para poder retrasar la inicialización hasta que algún evento de clic. JSFiddle of 1st answer actualizado con la segunda solución: jsfiddle.net/gavinfoley/G5ku5new
es declarativo y es fácil saber de inmediato qué servicios son singleton y cuáles no. Según si un objeto se está renovando.Otra forma es copiar el objeto de servicio con
angular.extend()
.y luego, por ejemplo, en su controlador
Aquí hay un golpe .
fuente
Sé que esta publicación ya ha sido respondida, pero sigo pensando que habría algunos escenarios legítimos en los que necesita tener un servicio que no sea singleton. Digamos que hay alguna lógica empresarial reutilizable que se puede compartir entre varios controladores. En este escenario, el mejor lugar para poner la lógica sería un servicio, pero ¿qué pasa si necesitamos mantener algún estado en nuestra lógica reutilizable? Luego, necesitamos un servicio que no sea singleton, por lo que se puede compartir entre diferentes controladores en la aplicación. Así es como implementaría estos servicios:
fuente
Aquí está mi ejemplo de un servicio no singleton, es de un ORM en el que estoy trabajando. En el ejemplo, muestro un modelo base (ModelFactory) que quiero que los servicios ('usuarios', 'documentos') hereden y puedan extender.
En mi ORM, ModelFactory inyecta otros servicios para proporcionar funcionalidad adicional (consulta, persistencia, mapeo de esquemas) que se coloca en un espacio aislado utilizando el sistema de módulos.
En el ejemplo, tanto el usuario como el servicio de documentos tienen la misma funcionalidad pero tienen sus propios ámbitos independientes.
fuente
angular solo ofrece una opción de fábrica / servicio singleton . una forma de evitarlo es tener un servicio de fábrica que creará una nueva instancia para usted dentro de su controlador u otras instancias de consumo. lo único que se inyecta es la clase que crea nuevas instancias. este es un buen lugar para inyectar otras dependencias o para inicializar su nuevo objeto a la especificación del usuario (agregando servicios o configuración)
luego, en su instancia de consumidor, necesita el servicio de fábrica y llama al método de compilación en la fábrica para obtener una nueva instancia cuando la necesite
puede ver que brinda la oportunidad de inyectar algunos servicios específicos que no están disponibles en el paso de fábrica. siempre puede hacer que la inyección ocurra en la instancia de fábrica para que la utilicen todas las instancias del modelo.
Tenga en cuenta que tuve que quitar algo de código para que pudiera cometer algunos errores de contexto ... si necesita una muestra de código que funcione, hágamelo saber.
Creo que NG2 tendrá la opción de inyectar una nueva instancia de su servicio en el lugar correcto en su DOM, por lo que no necesita crear su propia implementación de fábrica. Tendré que esperar y ver :)
fuente
Creo que hay una buena razón para crear una nueva instancia de un objeto dentro de un servicio. También deberíamos mantener la mente abierta en lugar de simplemente decir que nunca deberíamos hacer tal cosa, pero el singleton se hizo de esa manera por una razón . Los controladores se crean y destruyen a menudo durante el ciclo de vida de la aplicación, pero los servicios deben ser persistentes.
Puedo pensar en un caso de uso en el que tiene un flujo de trabajo de algún tipo, como aceptar un pago y tiene múltiples propiedades configuradas, pero ahora debe cambiar su tipo de pago porque la tarjeta de crédito del cliente falló y necesita proporcionar una forma diferente de pago. Por supuesto, esto tiene mucho que ver con la forma en que crea su aplicación. Puede restablecer todas las propiedades del objeto de pago o puede crear una nueva instancia de un objeto dentro del servicio . Pero no querrá una nueva instancia del servicio, ni querrá actualizar la página.
Creo que una solución es proporcionar un objeto dentro del servicio del que puede crear una nueva instancia y configurar. Pero, para que quede claro, la instancia única del servicio es importante porque un controlador puede crearse y destruirse muchas veces, pero los servicios necesitan persistencia. Es posible que lo que está buscando no sea un método directo dentro de Angular, sino un patrón de objeto que puede administrar dentro de su servicio.
Como ejemplo, hice un botón de reinicio . (Esto no está probado, en realidad es solo una idea rápida de un caso de uso para crear un nuevo objeto dentro de un servicio.
fuente
Aquí hay otro enfoque al problema con el que estaba bastante satisfecho, específicamente cuando se usa en combinación con Closure Compiler con optimizaciones avanzadas habilitadas:
fuente