LIBRERÍA ANGULAR. PARTE 3,5. SIRVIENDO

<script src=”my own” title=”parte 3,5. sirviendo”>

Entre el 3 y el 4, y antes de ponerme a escribir el siguiente post del tutorial, consideré importante abordar una parte importante (y tal vez más natural para el desarrollador) de Angular.js, y para eso es este “post intermedio” ( 😛 ). Se trata de los servicios en Angular.

Sirviendo

Hay muchos conceptos de arquitectura de sistemas que involucra la implantación de un “servicio”, visto desde el enfoque tradicional. En patrones de diseño, el modelo closure de Javascript provee una forma adecuada para conceptualizar un servicio, el cual (en Javascript, hablando del closure) no es más que un objeto global que tiene un comportamiento o influencia sobre cierta area del sistema en particular, pero que convive separado del resto del sistema.

"A grosso modo" lo que son servicios web

“A grosso modo” lo que son servicios web

Dicho esto, Angular.js tiene su forma particular de crear servicios bajo el mismo principio. En mi caso, diseñé un servicio que provee métodos de acceso a la interfaz de IndexedDB en el navegador, todo eso con el propósito de tener un componente CRUD de acceso a datos ¡a lo Javascript! 😀

var libreria = angular.module('libreria-angular'); //Se instancia de manera global

libreria.service('$crud', ['$q', function($q) {

	// Instancia de Dexie
	var _db = new Dexie('libreria-angular');

	// Estructura prototipo del objeto Libro
	var _Libro = function(o){
		this.titulo = o.titulo;
		this.autor = o.autor;
		this.anio = o.anio;
		this.categoria = o.categoria;
		this.precio = o.precio;
		this.inventario = o.inventario;
		this.existente = o.existente;
	};

	// TODO: Configuración genérica del esquema con $provide
	_db.version(1)
		.stores({
			listaLibros: '++id, titulo, autor, anio, categoria, precio, inventario, existente'
		});

	//Abrir conexión con BD ~ Cerrar conexión con BD
	var _abrir = function(){ _db.open(); };
	var _cerrar = function(){ _db.close(); };

	// Instancia del API Promises Q+ de Angular
	var _q = $q.defer();

	this.agregar = function(data){
		_abrir();
		_db.listaLibros.put(new _Libro(data)).then(function(data){
			_q.resolve(data); // Número de objetos insertados en la BD
		});
		_cerrar();
		return _q.promise;
	};
	...
}]);

Vale decir que el resto del código fuente del servicio (y las demás actualizaciones 🙂 ) está en mi repo. Ahora bien, hay mucho que resaltar:

  • Línea 3: Tal y como definimos una factory en el post anterior de este tutorial, usamos la palabra reservada service en este caso, luego el nombre del servicio, inyectando como dependencia el objeto global $q (del cual voy a hablar más adelante).
  • Línea 6: Uso Dexie.js en su versión minificada como componente de acceso a IndexedDB. Acá se define la instancia de la base de datos a ser creada, pueden ver su documentación para más información.
  • Línea 9: No hay mucho que decir, salvo que es el patrón de diseño que nos sirve de prototipo para tener un acceso uniforme de los datos ingresados en la Base de Datos, en comparación con la estructura presentada en la factory creada.
  • Linea 20: Se define el esquema de la base de datos. En IndexedDB, cada columna de una tabla relacional SQL es vista como “índice” de un mismo esquema. Queda pendiente el tema de realizar configuraciones de servicios con el objeto global $provide de Angular.js.
  • Línea 30: El objeto global $q y su método $q.defer() forman parte de la API Promises propia de Angular.js. En este post hablaba sobre Promises en Javascript, pero no dije que fuera la única forma de implementarlas (jejeje, zorry 😀 ).

    La API Promises Q+ es un enfoque distinto del visto en el post mencionado anteriormente. Fue creado por Kris Kowal, uno de los colaboradores de Angular.js. Este enfoque propone un manejo asíncrono y además paralelo de la resolución de Promises.

  • Líneas 33 y 37: Ningún misterio: abren y cierran conexión con la Base de Datos. En IndexedDB es buena práctica no dejar conexiones abiertas luego de realizar transacciones.
  • Línea 35: El método agregar() y todos los métodos del servicio $crud, tienen la misma aproximación asíncrona de resolución de Promises. Esto es así por la aproximación que utiliza la libreria Dexie.js para hacer transacciones a IndexedDB retornando Promises a ser resueltas. Esto es, luego de realizar la transacción, se hallan los datos que quedaron “por resolver” (método $q.defer())  en el envio de Promises.
  • Línea 38: Se retorna el Promise a ser manejado más adelante con la finalidad de hacerlo “genérico”.

Todos los métodos del servicio $crud tienen este enfoque de resolución de Promises, lo cual requiere que, en donde vaya a ser utilizado, sea resuelto de la forma indicada en este post, lo cual (y no todo es color de rosa) representa una complejidad extra en nuestro código.

¿Fabricando o Sirviendo?

Mucho se ha dicho (y se ha escrito) sobre el uso de services o factories en Angular.js, sin embargo es importante resaltar que: ¡SON SIMILARES!, pues en realidad ambas aproximaciones representan un closure, con la ÚNICA diferencia observable que en un factory se retorna un objeto, mientras que en un service no.

La decisión de usar uno u otro, debería ser definido por una cuestión propia de la arquitectura que estés diseñando, pero en cualquier caso, es bueno saber que cuentas con componentes variados que puedes utilizar en cualquier momento y para funcionalidades específicas dentro de tu aplicación. Aunque no es fijo ni estándar, se estila el uso un factory para compartir datos entre controladores, mientras que un service trabaja como interfaz de otras secciones de la aplicación.

Ahora a sumar +0,5 al tutorial. ¡Hasta el próximo post! 😉

</script>

Anuncios

Un comentario en “LIBRERÍA ANGULAR. PARTE 3,5. SIRVIENDO

Los comentarios están cerrados.