Introducción a los servicios

En este artículo vamos a sentar las bases del concepto y el uso de servicios e inyección de dependencias en Angular. Es un tema al que muchos se enfrentan con un poco de inquietud al principio, ya que, como en toda la informática actual, los conceptos se etiquetan con nombres que de grandilocuentes pasan, a veces, a ser intimidantes. Sin embargo, verás que los servicios en Angular son fáciles de entender, de crear y de usar, y que el mismo concepto llevamos usándolo toda la vida, aunque lo hayamos empleado de otros modos, en otros contextos y con otros nombres.

Para facilitar las cosas, este es un miniartículo meramente teórico, en el que sentaremos las bases de lo que son los servicios en Angular, y la forma de emplearlos, en una visión muy general. Será en el próximo artículo donde mostraremos ejemplos prácticos que ilustren, realmente, esta herramienta. Posteriormente, como hemos ido haciendo con el resto de conceptos que hemos aprendido, los usaremos en otros proyectos, para facilitarnos su práctica.

DEFINICIÓN DE SERVICIOS

Un servicio es una pieza de código destinada a cumplir una misión específica, que puede ser incluido (inyectado) en aquellos puntos de la aplicación donde se deba desempeñar dicha misión. Si te pones a pensarlo, con esa definición, cualquier aplicación web desarrollada en Angular podría estar constituida casi en su totalidad por servicios. Sin embargo, en la práctica, siempre hay que buscar un equilibrio en el uso de los servicios (como en el uso de todo, en realidad). La cuestión es emplear sevicios para encapsular aquellas tareas que deban llevarse a cabo (o que, previsiblemente, puedan tener que llevarse a cabo) en más de un componente de la aplicación. De este modo se logra un alto nivel de desacoplamiento y cuando necesitemos modificar o escalar esas tareas, sólo tendremos que trabajar sobre el servicio que nos interese, evitando tener que tocar en más puntos de la aplicación.

En definitiva, cuanto más acotadas y concretizadas estén las tareas que llevan a cabo los servicios y componentes (lo que se conoce como atomización de la aplicación) y más desacoplado esté todo, más fácil nos resultará el mantenimiento y escalado de nuestra aplicación. Muchos desarrolladores (sobre todo los de la vieja escuela, que tenemos «vicios chungos» muy arraigados) tenedemos, de una forma casi natural a reinventar la rueda cada vez que necesitamos hacer algo que ya tenemos hecho en otra parte. Esa es, desde luego, una de las perores cosas que se pueden hacer en programación y que, a día de hoy, nadie en este sector puede permitirse. El uso de servicios inyectables nos permite hacer las cosas «al estilo de hoy» con mucha facilidad, y de una forma muy instintiva y natural.

ÁMBITO DE LOS SERVICIOS

Los servicios en una aplicación Angular pueden crearse para ser usados en tres ámbitos distintos:

A nivel de toda la aplicación. Serán servicios que estén disponibles desde cualquier componente de la aplicación. Se definen en un directorio específico que se crea dentro de la ruta raíz (src/app/) y que, por lo tanto, pueden ser inyectados en cualquier componente. Si nuestra aplicación emplea muchos de esos servicios, el directorio que creemos podría, a su vez, tener una jerarquía de subdirectorios a efectos organzativos.

  • A nivel de módulo. Son servicios que sólo se van a emplear en un módulo. Se definen en el directorio de dicho módulo, y estarán disponibles para todos los componentes del mismo.
  • A nivel de componente. Son servicios que se crean dentro del módulo donde vive el componente que los vaya a emplear, y que sólo se inyectan en dicho componente.
  • En la práctica la última opción se funde un poco con la primera, definiendo los servicios a nivel de módulo, y empleándolos en aquél o aquellos componentes del módulo que lo requieran.

Lo que sí tienes que tener en cuenta es que un servicio que vaya a cumplir una tareas específica no debe replicarse en la aplicación. Suponte que tu aplicación tiene, digamos, diez módulos. Y ahora creas un servicio que vas a emplear en dos de tales módulos. No lo crearás a nivel de mósulo para cada uno de esos dos módulos que lo van a emplear: lo crearás a nivel global de aplicación, y lo inyectarás en los dos módulos interesados. De este modo, ahorrarás código, aumentarás el desacoplamiento y facilitarás la mantenibilidad y escalabilidad de tu aplicación. Si, posteriormente, necesitaras el servicio en otro módulo, simplemente, lo inyectarás también, no tendrás que replicarlo.

ESTRUCTURA BÁSICA DE UN SERVICIO

Para crear un servicio en nuestra aplicación empleamos el comando siguiente:

ng generate service [ruta/]nombre-del-servicio

o, abreviadamente:

ng g s [ruta/]nombre-del-servicio

Por ejemplo, vamos a crear un servicio al que llamaremos, por ejemplo, lectura-datos. Lo vamos a crear a nivel global de la aplicación. Por lo tanto, en la ruta raíz del proyecto (src/app/) crearemos un directorio llamado global-services. El servicio lo crearemos con la instrucción siguiente:

ng g s global-services/lectura-datos

El Angular CLI ha creado dos archivos, como vemos en la respuesta de la terminal:

create src/app/global-services/lectura-datos.service.spec.ts (411 bytes)
create src/app/global-services/lectura-datos.service.ts (118 bytes)

El archivo que tiene la terminación .spec.ts es, como ocurre con los componentes, para las pruebas unitarias. Es algo de lo que no vamos a hablar en este momento. Vamos a centrarnos en el otro archivo, que es donde definiremos nuestro servicio. Su código inicial es el siguiente:

Lo primero que vemos, en la línea 1, es que se importa, del núcleo de Angular, la interface Injectable, necesaria para poder inyectar nuestro servicio en donde nos haga falta.

En la línea 3 se declara el decorador @Injectable(), que usaremos más adelante, y que es el que implementa la interfaz Injectable en nuestro servicio.

En la línea 4 se declara y exporta la clase del servicio, cuyo nombre es el que le hemos dado (siguiendo las nosrmas que ya conocemos de nomenclatura de Angular), con el sufijo Service. Este sufijo es añadido de forma automática a todos los servicios de Angular, a título semántico.

INYECTANDO EL SERVICIO

Crear un servicio es, desde luego, sólo una parte del trabajo. Además, tenemos que inyectarlo en el módulo donde lo vayamos a emplear. Como este servicio lo hemos definido a nivel global del módulo, asumiremos que va a contener algún código que necesitaremos, o podremos necesitar, en cualquier parte de la aplicación. Y, como sabemos que el componente raíz (AppComponent) que es parte del módulo raíz (AppModule) se carga en cualquier componente que usemos (ya lo hemos visto en múltiples ocasiones), lo inyectaremos en la aplicación mediante el archivo app.module.ts. El listado original de este archivo (con la aplicación recién creada), es el siguiente:

La forma de inyectar un servicio en un módulo es parecida, conceptualmente, a importar un módulo o componente. Tenemos que importarlo, y declararlo en el decorador @NgModule. Sin embargo, no usaremos la clave imports. En su lugar, para los servicios usamos la clave providers que, hasta ahora, no habíamos empleado para nada. El listado de app.module.ts con la iyección del servicio queda así:

Observa, en las dos líneas resaltadas, como hacemos la importación y lo incluimos, como te he comentado, en la clave providers.

CONCLUYENDO

En este artículo hemos aprendido lo que es un servicio, sentando las bases teóricas para su inyección y uso. En el próximo artículo veremos un ejemplo práctico del uso de servicios en una aplicación muy simple, pero que ilustrará el funcionamiento de esta herramienta.

   

Deja un comentario