Factorías (factory) en AngularJS

| 2015-03-21 | No hay comentarios »

Qué son las factorías

Las factorías son como contenedores de código que podemos usar en nuestros sitios desarrollados con AngularJS. Son un tipo de servicio, “service” en Angular, con el que podemos implementar librerías de funciones o almacenar datos.

2992

Cuando las usamos tienen la particularidad de devolvernos un dato, de cualquier tipo. Lo común es que nos devuelvan un objeto de Javascript donde podremos encontrar datos (propiedades) y operaciones (métodos). Con diferencia de los controladores, las factorías tienen la característica de ser instanciados una única vez dentro de las aplicaciones, por lo que no pierden su estado. Por tanto, son un buen candidato para almacenar datos en nuestra aplicación que queramos usar a lo largo de varios controladores, sin que se inicialicen de nuevo cuando se cambia de vista.

Angular consigue ese comportamiento usando el patrón “Singleton” que básicamente quiere decir que, cada vez que se necesite un objeto de ese tipo, se enviará la misma instancia de ese objeto en lugar de volver a instanciar un ejemplar.

Notas sobre los “services” en Angular

Los “services” en AngularJS incluyen tanto factorías como servicios. Más adelante veremos la diferencia. Lo que queremos mencionar ahora es que estos contenedores de código ya los hemos usado en diversas ocasiones y quizás podrás entender su utilidad mejor si analizamos cosas que ya conoces.

Por ejemplo, cuando estás haciendo Ajax, por los métodos que hemos conocido hasta el momento, usamos $http. Éste no es más que un service de Angular que engloba toda la funcionalidad necesaria para realizar solicitudes asíncronas a un servidor.

Por tanto, algo como Ajax, que se supone que puedes querer realizar a lo largo de tu aplicación en varias partes del código, se ha separado a un “servicio”. Esto quiere decir que, cuando quieras hacer Ajax, tendrás que usar el código del “service” $http.

Los servicios y factorías que desees usar en tus controladores o módulos deberás inyectarlos como has visto hacer en diversas partes de nuestros ejemplos. No te preocupes si no lo recuerdas porque a continuación veremos ejemplos.

Ejemplo de factoría en AngularJS

Ahora nos vamos a poner manos a la obra creando nuestra primera factoría. Para ello vamos a continuar con el ejercicio que hemos visto en los artículos anteriores del Manual de AngularJS. Como recordarás, queremos implementar un sistema que nos memorice cierta información de nuestra aplicación a lo largo de diversas vistas.

Implementamos factorías con el método factory() que depende del módulo (objeto module) de nuestra aplicación.

Osea, como cualquier aplicación de Angular, lo primero crearás tu “module” principal:

angular.module("app", ["ngRoute"])

Y sobre el objeto que devuelve esa operación crearemos las factorías.

.factory("descargasFactory", function(){
    var descargasRealizadas = ["Manual de Javascript", "Manual de jQuery", "Manual de AngularJS"];

    var interfaz = {
        nombre: "Manolo",
        getDescargas: function(){
            return descargasRealizadas;
        },
        nuevaDescarga: function(descarga){
            descargasRealizadas.push(descarga);
        }
    }
    return interfaz;
})

Esta factoría se llama “descargasFactory”. El nombre lo hemos definido en la llamada al método factory. Acuérdate de este nombre, pues luego lo tendrás que usar al inyectar la dependencia de esta factoría en tus controladores.

Ese código tiene una serie de detalles interesantes, desde el punto de vista de Angular y también desde el de Javascript en general. Estudiar el código anterior con detalle es suficiente para un único artículo, porque entran en juego diversos conceptos de la programación orientada a objetos en Javascript. De todos modos, te vamos a resumir un poco lo que encuentras.

  • Lo más destacado sobre las factorías en AngularJS lo encuentras en la última línea: “return interfaz;” Todas las factorías deben devolver algo. Lo que sea, aunque lo habitual como dijimos es devolver un objeto. Por definición debe de ser así en AngularJS.
  • Aquello que devuelves es lo que se conoce desde fuera de la factoría. Por decirlo de otra manera, es la interfaz pública de uso de esa factoría. Por eso hemos llamado a la variable que devolvemos en el return “interfaz”, porque es la serie de propiedades y métodos que estás haciendo público para todo el mundo que use esa factoría. Lógicamente, esa “interfaz” no es más que una manera nuestra de llamar a la variable y tú usarás la que quieras.
  • Pero fíjate que la variable “descargasRealizadas” es privada a la factoría, pues no se devuelve en la interfaz. Por tanto, ese array no podrá ser accesible desde fuera de la factoría. Podemos entenderlo como una propiedad privada.
  • Para acceder al array “descargasRealizadas” se hará uso de los métodos definidos en “interfaz”: getDescargas() y nuevaDescarga(). Esos métodos son públicos, por haberlos definido en la interfaz que devolvemos en la función de la factoría y se podrán acceder desde cualquier lugar donde tengamos disponible la factoría.
  • Sin embargo no todos los datos que vamos a manejar en las factorías necesitamos hacerlos privados. En concreto encontrarás, la propiedad “nombre” que está dentro de nuestra interfaz y por lo tanto es pública y podrá accederse tal cual desde fuera de la factoría.

Usar una factoría

Ahora podemos ver cómo usar la factoría que acabamos de realizar. El procedimiento es tan simple como, una vez definida, inyectarla en el controlador donde la queremos usar. Usamos el sistema de inyección de dependencias que ya conoces.

Al crear la función del controlador debemos definir un parámetro que se llame exactamente igual al nombre que le has dado en la factoría. En este caso el parámetro que inyectamos en el controlador se llama “descargasFactory” pues así habíamos llamado a la factoría al crearla.

Echa ahora un vistazo a un controlador que usa esta factoría.

.controller("appCtrl", function(descargasFactory){
    var vm = this;
    
    vm.nombre = descargasFactory.nombre;
    vm.descargas = descargasFactory.getDescargas();
    vm.funciones = {
        guardarNombre: function(){
            descargasFactory.nombre = vm.nombre;
        },
        agregarDescarga: function(){
            descargasFactory.nuevaDescarga(vm.nombreNuevaDescarga);
            vm.mensaje = "Descarga agregada";
        },
        borrarMensaje: function(){
            vm.mensaje = "";
        }
    }
});

Dentro de nuestro controlador la variable descargasFactory que recibimos como parámetro contiene todos los datos y funciones que hemos definido en la interfaz pública de nuestra factoría.

Por tanto:

– descargasFactory.nombre contendrá la propiedad “nombre” definida en la factory.
– descargasFactory.nuevaDescarga() o descargasFactory.getDescargas() serán llamadas a los métodos que habíamos definido en la factoría.

Creo que con todo esto queda explicado el trabajo con las factorías en AngularJS. Ahora faltaría un poco de tiempo por tu parte para poder ponerlo en práctica.

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • Tutorial: Crear una aplicación web utilizando MEAN
  • Qué es y cómo empezar con Ionic Framework
  • Scope en AngularJS, manejando ámbitos con $parent
  • Introducción a $location y primeros controladores en paralelo en AngularJS



SEGUÍNOS EN FACEBOOK


GITHUB