He visto que angular.factory () y angular.service () se utilizan para declarar servicios; Sin embargo, no puedo encontrar angular.service
ningún lugar en la documentación oficial.
¿Cuál es la diferencia entre los dos métodos?
¿Cuál debería usarse para qué (suponiendo que hagan cosas diferentes)?
angularjs
angular-services
jacob
fuente
fuente
Respuestas:
Tuve problemas para comprender este concepto hasta que me lo planteé de esta manera:
Servicio : la función que escriba será nueva :
Fábrica : se invocará la función (constructor) que escriba :
Lo que hagas con eso depende de ti, pero hay algunos patrones útiles ...
Como escribir una función de servicio para exponer una API pública:
O usando una función de fábrica para exponer una API pública:
O usando un función de fábrica para devolver un constructor:
¿Cuál usar?
Puedes lograr lo mismo con ambos. Sin embargo, en algunos casos la fábrica le brinda un poco más de flexibilidad para crear un inyectable con una sintaxis más simple. Eso es porque mientras myInjectedService siempre debe ser un objeto, myInjectedFactory puede ser un objeto, una referencia de función o cualquier valor. Por ejemplo, si escribió un servicio para crear un constructor (como en el último ejemplo anterior), debería crearse una instancia de esta manera:
lo cual es posiblemente menos deseable que esto:
(Pero debe tener cuidado al usar este tipo de patrón en primer lugar porque es nuevo objetos en sus controladores crean dependencias difíciles de rastrear que son difíciles de burlar para las pruebas. Es mejor tener un servicio que administre una colección de objetos para que usar
new()
astutamente)Una cosa más, todos son Singletons ...
También tenga en cuenta que en ambos casos, angular le ayuda a administrar un singleton. Independientemente de dónde o cuántas veces inyecte su servicio o función, obtendrá la misma referencia al mismo objeto o función. (Con la excepción de cuando una fábrica simplemente devuelve un valor como un número o una cadena. En ese caso, siempre obtendrá el mismo valor, pero no una referencia).
fuente
new fn()
, por lo que deben devolver una instancia.Simplemente pon ..
fuente
Aquí están las principales diferencias:
Servicios
Sintaxis:
module.service( 'serviceName', function );
Resultado: al declarar serviceName como argumento inyectable, se le proporcionará la instancia de una función pasada a
module.service
.Uso: podría ser útil para compartir funciones de utilidad que son útiles para invocar simplemente agregando
( )
a la referencia de función inyectada. También podría ejecutarse coninjectedArg.call( this )
o similar.Suerte
Sintaxis:
module.factory( 'factoryName', function );
Resultado: al declarar factoryName como argumento inyectable, se le proporcionará el valor que se devuelve invocando la referencia de función pasada a
module.factory
.Uso: podría ser útil para devolver una 'clase' que luego se puede actualizar para crear instancias.
Aquí hay un ejemplo de uso de servicios y fábrica . Leer más sobre AngularJS Service vs Factory .
También puede consultar la documentación de AngularJS y una pregunta similar sobre stackoverflow confundido sobre el servicio frente a la fábrica .
fuente
$providers
todo el tiempo.this.myFunc = function(){}
en su servicio (le ahorra escribir código para crear el objeto como lo haría con una fábrica )TL; DR
1) Cuando utiliza una Fábrica , crea un objeto, le agrega propiedades y luego devuelve el mismo objeto. Cuando pasa esta fábrica a su controlador, esas propiedades en el objeto ahora estarán disponibles en ese controlador a través de su fábrica.
2) Cuando usa el Servicio , Angular lo instancia detrás de escena con la palabra clave 'nuevo'. Debido a eso, agregará propiedades a 'this' y el servicio devolverá 'this'. Cuando pasa el servicio a su controlador, esas propiedades en 'esto' ahora estarán disponibles en ese controlador a través de su servicio.
No TL; DR
1)
Fábricas Las fábricas son la forma más popular de crear y configurar un servicio. Realmente no hay mucho más de lo que dice el TL; DR. Simplemente crea un objeto, le agrega propiedades y luego devuelve el mismo objeto. Luego, cuando pase la fábrica a su controlador, esas propiedades en el objeto ahora estarán disponibles en ese controlador a través de su fábrica. Un ejemplo más extenso está abajo.
Ahora, cualquier propiedad que adjuntemos al 'servicio' estará disponible cuando pasemos 'myFactory' a nuestro controlador.
Ahora agreguemos algunas variables 'privadas' a nuestra función de devolución de llamada. Estos no serán accesibles directamente desde el controlador, pero eventualmente configuraremos algunos métodos getter / setter en 'servicio' para poder alterar estas variables 'privadas' cuando sea necesario.
Aquí notará que no estamos asociando esas variables / funciones a 'servicio'. Simplemente los estamos creando para usarlos o modificarlos más tarde.
Ahora que nuestras funciones y variables auxiliares / privadas están en su lugar, agreguemos algunas propiedades al objeto 'servicio'. Independientemente de lo que le demos al 'servicio', podremos usarlo directamente en cualquier controlador al que le pasemos 'myFactory'.
Vamos a crear métodos setArtist y getArtist que simplemente devuelven o configuran al artista. También vamos a crear un método que llame a la API de iTunes con nuestra URL creada. Este método devolverá una promesa que se cumplirá una vez que los datos hayan regresado de la API de iTunes. Si no ha tenido mucha experiencia usando promesas en Angular, le recomiendo que profundice en ellas.
A continuación, setArtist acepta un artista y le permite configurarlo. getArtist devuelve el artista callItunes primero llama a makeUrl () para construir la URL que usaremos con nuestra solicitud $ http. Luego configura un objeto de promesa, realiza una solicitud de $ http con nuestra url final, luego, debido a que $ http devuelve una promesa, podemos llamar a .success o .error después de nuestra solicitud. Luego resolvemos nuestra promesa con los datos de iTunes, o la rechazamos con un mensaje que dice 'Hubo un error'.
Ahora nuestra fábrica está completa. Ahora podemos inyectar 'myFactory' en cualquier controlador y luego podremos llamar a nuestros métodos que adjuntamos a nuestro objeto de servicio (setArtist, getArtist y callItunes).
En el controlador anterior, estamos inyectando en el servicio 'myFactory'. Luego establecemos propiedades en nuestro objeto $ scope que provienen de datos de 'myFactory'. El único código complicado anterior es si nunca antes ha tratado con promesas. Debido a que callItunes está devolviendo una promesa, podemos usar el método .then () y solo establecemos $ scope.data.artistData una vez que nuestra promesa se cumpla con los datos de iTunes. Notarás que nuestro controlador es muy 'delgado'. Todos nuestros datos lógicos y persistentes se encuentran en nuestro servicio, no en nuestro controlador.
2) servicio
Quizás lo más importante que se debe saber cuando se trata de crear un Servicio es que se instancia con la palabra clave 'nueva'. Para sus gurús de JavaScript, esto debería darle una gran pista sobre la naturaleza del código. Para aquellos de ustedes con antecedentes limitados en JavaScript o para aquellos que no están demasiado familiarizados con lo que realmente hace la 'nueva' palabra clave, revisemos algunos fundamentos de JavaScript que eventualmente nos ayudarán a comprender la naturaleza de un Servicio.
Para ver realmente los cambios que ocurren cuando invoca una función con la palabra clave 'nueva', creemos una función e invoquémosla con la palabra clave 'nueva', luego muestremos qué hace el intérprete cuando ve la palabra clave 'nueva'. Los resultados finales serán los mismos.
Primero creemos nuestro Constructor.
Esta es una función típica de constructor de JavaScript. Ahora, cada vez que invoquemos la función Persona usando la palabra clave 'nuevo', 'esto' estará vinculado al objeto recién creado.
Ahora agreguemos un método al prototipo de nuestra Persona para que esté disponible en cada instancia de nuestra 'clase' de Persona.
Ahora, debido a que ponemos la función sayName en el prototipo, cada instancia de Person podrá llamar a la función sayName para alertar el nombre de esa instancia.
Ahora que tenemos nuestra función de constructor Person y nuestra función sayName en su prototipo, creemos una instancia de Person y luego llamemos a la función sayName.
Entonces, todo el código para crear un constructor de Persona, agregar una función a su prototipo, crear una instancia de Persona y luego llamar a la función en su prototipo se ve así.
Ahora echemos un vistazo a lo que realmente está sucediendo cuando usa la palabra clave 'nuevo' en JavaScript. Lo primero que debe notar es que después de usar 'nuevo' en nuestro ejemplo, podemos llamar a un método (sayName) en 'tyler' como si fuera un objeto, eso es porque lo es. Primero, sabemos que nuestro constructor de Persona está devolviendo un objeto, ya sea que podamos ver eso en el código o no. En segundo lugar, sabemos que debido a que nuestra función sayName se encuentra en el prototipo y no directamente en la instancia de Person, el objeto que devuelve la función Person debe delegarse en su prototipo en búsquedas fallidas. En términos más simples, cuando llamamos a tyler.sayName () el intérprete dice "OK, voy a buscar el objeto 'tyler' que acabamos de crear, ubicar la función sayName y luego llamarla. Espera un momento, no lo veo aquí, todo lo que veo es nombre y edad, Déjame comprobar el prototipo. Sí, parece que está en el prototipo, déjenme llamarlo ".
A continuación se muestra el código de cómo puede pensar qué está haciendo la palabra clave 'nueva' en JavaScript. Básicamente es un ejemplo de código del párrafo anterior. Puse la 'vista del intérprete' o la forma en que el intérprete ve el código dentro de las notas.
Ahora que conocemos lo que realmente hace la 'nueva' palabra clave en JavaScript, crear un Servicio en Angular debería ser más fácil de entender.
Lo más importante para entender al crear un Servicio es saber que los Servicios se instancian con la palabra clave "nueva". Combinando ese conocimiento con nuestros ejemplos anteriores, ahora debería reconocer que adjuntará sus propiedades y métodos directamente a 'esto', que luego será devuelto por el Servicio mismo. Echemos un vistazo a esto en acción.
A diferencia de lo que hicimos originalmente con el ejemplo de Factory, no necesitamos crear un objeto y luego devolverlo porque, como se mencionó muchas veces antes, usamos la palabra clave 'new' para que el intérprete cree ese objeto, haga que delegue en es prototipo, luego devuélvanoslo sin que tengamos que hacer el trabajo.
Primero lo primero, creemos nuestra función 'privada' y auxiliar. Esto debería parecer muy familiar ya que hicimos exactamente lo mismo con nuestra fábrica. No explicaré qué hace cada línea aquí porque lo hice en el ejemplo de fábrica, si está confundido, vuelva a leer el ejemplo de fábrica.
Ahora, adjuntaremos todos nuestros métodos que estarán disponibles en nuestro controlador a 'esto'.
Ahora, al igual que en nuestra fábrica, setArtist, getArtist y callItunes estarán disponibles en cualquier controlador al que pasamos myService. Aquí está el controlador myService (que es casi exactamente el mismo que nuestro controlador de fábrica).
Como mencioné antes, una vez que realmente comprende lo que hace 'nuevo', los Servicios son casi idénticos a las fábricas en Angular.
fuente
La pista está en el nombre
Los servicios y las fábricas son similares entre sí. Ambos producirán un objeto singleton que se puede inyectar en otros objetos y, por lo tanto, a menudo se usan indistintamente.
Están destinados a ser utilizados semánticamente para implementar diferentes patrones de diseño.
Los servicios son para implementar un patrón de servicio
Un patrón de servicio es aquel en el que su aplicación se divide en unidades de funcionalidad lógicamente consistentes. Un ejemplo podría ser un descriptor de acceso a la API o un conjunto de lógica empresarial.
Esto es especialmente importante en Angular porque los modelos angulares generalmente son solo objetos JSON extraídos de un servidor, por lo que necesitamos un lugar para poner nuestra lógica de negocios.
Aquí hay un servicio de Github, por ejemplo. Sabe hablar con Github. Sabe sobre urls y métodos. Podemos inyectarlo en un controlador, y generará y devolverá una promesa.
Las fábricas implementan un patrón de fábrica
Las fábricas, por otro lado, están destinadas a implementar un patrón de fábrica. Un patrón de fábrica en el que usamos una función de fábrica para generar un objeto. Por lo general, podríamos usar esto para construir modelos. Aquí hay una fábrica que devuelve un constructor Autor:
Haríamos uso de esto así:
Tenga en cuenta que las fábricas también devuelven singletons.
Las fábricas pueden devolver un constructor
Como una fábrica simplemente devuelve un objeto, puede devolver cualquier tipo de objeto que desee, incluida una función de constructor, como vemos más arriba.
Las fábricas devuelven un objeto; los servicios son renovables
Otra diferencia técnica está en la forma en que se componen los servicios y las fábricas. Se actualizará una función de servicio para generar el objeto. Se llamará a una función de fábrica y devolverá el objeto.
Esto significa que en un servicio, agregamos "esto" que, en el contexto de un constructor, apuntará al objeto en construcción.
Para ilustrar esto, aquí está el mismo objeto simple creado usando un servicio y una fábrica:
fuente
Author
debería estar el parámetro del inyectorPerson
.Todas las respuestas aquí parecen estar relacionadas con el servicio y la fábrica, y eso es válido ya que eso era lo que se preguntaba. Pero también es importante tener en cuenta que hay varios otros
provider()
, incluidosvalue()
, yconstant()
.La clave para recordar es que cada uno es un caso especial del otro. Cada caso especial en la cadena le permite hacer lo mismo con menos código. Cada uno también tiene alguna limitación adicional.
Para decidir cuándo usar cuál solo ve cuál le permite hacer lo que quiere en menos código. Aquí hay una imagen que ilustra cuán similares son:
Para obtener un desglose completo paso a paso y una referencia rápida de cuándo usar cada uno, puede visitar la publicación del blog de donde obtuve esta imagen:
http://www.simplygoodcode.com/2015/11/the-difference-between-service-provider-and-factory-in-angularjs/
fuente
app.factory ('fn', fn) versus app.service ('fn', fn)
Construcción
Con las fábricas, Angular invocará la función para obtener el resultado. Es el resultado que se almacena en caché e inyectado.
Con los servicios, Angular invocará la función constructora llamando a new . La función construida se almacena en caché e inyecta.
Implementación
Las fábricas suelen devolver un objeto literal porque el valor de retorno es lo que se inyecta en los controladores, bloques de ejecución, directivas, etc.
Las funciones de servicio generalmente no devuelven nada. En cambio, realizan la inicialización y exponen funciones. Las funciones también pueden hacer referencia a 'esto' ya que se construyó usando 'nuevo'.
Conclusión
Cuando se trata de usar fábricas o servicios, ambos son muy similares. Se inyectan en controladores, directivas, bloques de ejecución, etc., y se usan en el código del cliente de la misma manera. También son ambos singletons, lo que significa que la misma instancia se comparte entre todos los lugares donde se inyecta el servicio / fábrica.
Entonces, ¿cuál debería preferir? Cualquiera de los dos: son tan similares que las diferencias son triviales. Si elige uno sobre el otro, solo tenga en cuenta cómo se construyen, para que pueda implementarlos correctamente.
fuente
He pasado algún tiempo tratando de descubrir la diferencia.
Y creo que la función de fábrica usa el patrón de módulo y la función de servicio usa el patrón estándar de Java Script Constructor.
fuente
El patrón de fábrica es más flexible, ya que puede devolver funciones y valores, así como objetos.
No tiene mucho sentido en el patrón de servicio en mi humilde opinión, ya que todo lo que hace puede hacerlo fácilmente con una fábrica. Las excepciones pueden ser:
Podría decirse que el patrón de servicio es una forma un poco mejor de crear un nuevo objeto desde el punto de vista de la sintaxis, pero también es más costoso crear instancias. Otros han indicado que angular usa "nuevo" para crear el servicio, pero esto no es del todo cierto, no puede hacerlo porque cada constructor de servicios tiene un número diferente de parámetros. Lo que angular realmente hace es usar el patrón de fábrica internamente para ajustar su función de constructor. Luego, hace un poco de ingenioso juego de jiggery para simular el "nuevo" operador de JavaScript, invocando a su constructor con un número variable de argumentos inyectables, pero puede omitir este paso si solo usa el patrón de fábrica directamente, lo que aumenta ligeramente la eficiencia de su código.
fuente
function MyFactory(dep1) { var $$foo = 'bar', factory = {}; Object.defineProperties(factory.prototype, { foo: { value: $$foo } }); return factory; }
function MyService(dep1) { var $$foo = 'bar'; Object.defineProperties(MyService.prototype, { foo: { value: $$foo } }); }
Si bien MyFactory y MyService usan un prototipo, MyFactory aún sufre un impacto en el rendimiento al tener que construir el objeto que se devuelve. En ambos ejemplos, tienen elementos privados, pero en MyService no hay diferencias de rendimiento.MyFactory(someArgument)
(ej$http()
.). Eso no es posible con un servicio como usted estaría haciendo referencia al constructor:MyService(someArgument)
.