¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
¡Acceso ilimitado 24/7 a todos nuestros libros y vídeos! Descubra la Biblioteca Online ENI. Pulse aquí
  1. Libros
  2. Angular
  3. Los servicios
Extrait - Angular Desarrolle sus aplicaciones web con el framework JavaScript de Google
Extractos del libro
Angular Desarrolle sus aplicaciones web con el framework JavaScript de Google
2 opiniones
Volver a la página de compra del libro

Los servicios

Introducción

En este capítulo se abordará el aspecto de los servicios Angular. Se tratarán los puntos relativos a su declaración y su utilización. También veremos cómo gestionar las operaciones asíncronas dentro de un servicio, así como la noción de notificación de cambio de los datos.

¿Qué es un servicio?

El objetivo de un servicio es contener toda la lógica funcional y/o técnica de la aplicación. Al contrario de lo que sucede con los componentes, que solo deben contener la lógica propia de la operación de sus datos.

Uno de los ejemplos que normalmente se usan mucho, es encapsular las interacciones con un API en un servicio, para que el componente no tenga que preocuparse de los aspectos técnicos relacionados con la comunicación.

Un componente que consume un servicio, sencillamente debe solicitar los objetos y recuperar los. No tiene que preocuparse de los mecanismos y transformaciones implementadas para recuperar estos datos.

Declarar su servicio

La declaración de un servicio se hace creando una simple clase TypeScript. Los métodos públicos de esta clase, se expondrán y usarán por el resto de los elementos de la aplicación.

Si el servicio depende de otros servicios, es necesario añadirle el decorador @Injectable. En efecto, esto va a indicar a Angular que tiene que inyectar las dependencias de este servicio durante su resolución. Por lo tanto, este decorador no es obligatorio cuando el servicio no tiene ninguna dependencia, pero en todos los casos supone una buena práctica que le aconsejamos.

De esta manera, para crear un servicio que devuelve sencillamente una sucesión de números, es suficiente con realizar una clase como la siguiente:

import { Injectable } from '@angular/core';  
  
@Injectable()  
export class NumberService{  
    getFirstFiveNumbers(): number[]{  
        return [0,1,2,3,4];  
    }  
} 

Solo falta inyectar este servicio en un componente para empezar a usarlo.

Utilizar su servicio

Es deseable crear manualmente una instancia del servicio con ayuda de la palabra clave new, por dos razones principales.

En primer lugar, esto significaría que los componentes deben saber quién es el constructor de los servicios que están utilizando. De esta manera, si estos evolucionan, será necesario volver a cada componente usando estos servicios. Además, esto significa que es responsabilidad del componente gestionar el ciclo de vida del servicio y recuperar sus dependencias.

A continuación, esto significaría que se crea una nueva instancia del servicio durante cada llamada de cada componente usando este servicio. Los escenarios de almacenamiento en caché de datos se vuelven muy complicados de implementar en esta situación.

Por lo tanto, con el objetivo de poder utilizar un servicio, es preferible inyectarlo. Esto se hace en dos etapas principales.

Para empezar, hay que añadir un argumento privado en el constructor del componente. Este argumento debe tener el tipo del servicio. Así es como Angular reconoce que un componente depende de un servicio.

constructor(private servicio: Service){} 

Sin embargo, todavía hay que indicarle al framework dónde debe buscar este servicio. Para esto, Angular necesita que le indiquemos un proveedor. Para especificarlo a nivel de un componente, es suficiente con añadirlo al metadato providers del decorador...

Hacer su servicio asíncrono

La mayor parte del tiempo, un servicio va a tener la función de recuperar los datos en un servidor. Sin embargo, no hay que bloquear el programa durante la recuperación de estos datos. Para esto, a continuación se muestran dos métodos con el objetivo de hacer un servicio asíncrono.

1. Las promesas

Las promesas son un componente de la especificación ECMAScript 6. Son las "promesas" las que permiten ejecutar código solo cuando han terminado su trabajo.

Por lo tanto, funcionan con un callback que va a recibir la información devuelta por estas promesas. Estas también tienen un segundo callback que permite la gestión de los errores.

promesa.then((result) => console.log(result),  
            (error) => console.log(error)); 

En este ejemplo, se muestra el resultado de una promesa. El callback de éxito muestra el valor devuelto por la promesa y el callback de error muestra el error que se ha producido.

Las promesas solo tienen tres estados. En un primer momento, la promesa va a estar en el estado "pending", es decir, un estado que indica que la promesa se está ejecutando. A continuación la promesa puede pasar al estado "fulfilled", cuando todo ha terminado correctamente o al estado "rejected", cuando se produce un error durante el tratamiento.

Las promesas exponen los métodos then y catch. Estos dos métodos reciben como argumento un callback, que se llamará respectivamente cuando la promesa pase al estado "fulfilled" o "rejected".

import { NumberService } from './number-servicio';  
import { Component } from '@angular/core';  
  
@Component({  
  selector: 'numbers',  
  templateUrl: 'numbers.html',  
  providers: [NumberService]  
})  
export class NumberComponent{  
    numbers: number[];  
  
    constructor(private numberService: NumberService){  
        this.numberService.getFirstFiveNumbers()  
            .then(numbers => this.numbers = numbers)  
            .catch(error =>...

Notificar cuando los datos cambian

Gracias a RxJS, es posible notificar todos los elementos abonados de un cambio de datos dentro de un servicio.

Este es el comportamiento que se podría realizar con AngularJs usando el servicio $rootScope y su método broadcast.

Para llegar a este resultado con Angular, hay que utilizar la clase Subject o una de sus derivadas. Esta clase implementa al mismo tiempo Observable (es posible suscribirse) y Observer (por lo tanto, es posible llamar al método next como en el método Observable.create).

let subject = new Subject<string>();  
subject.subscribe(x => console.log(x));  
subject.next('hello');  
subject.next('world'); 

En este ejemplo, el callback que se pasa durante la suscripción se va a ejecutar dos veces: una para cada llamada del método next. Por lo tanto, el resultado de estas pocas líneas de código va a ser una visualización de "hello world" en la consola.

También es posible llamar a los otros métodos de la clase Observer. Por ejemplo, es posible terminar el observable llamando al método complete. Se ignorarán las acciones realizadas a continuación en el Subject.

let subject = new Subject<string>();  
subject.subscribe(x => console.log(x));  
subject.next('hello');  
subject.complete();  
subject.next('world'); 

Por lo tanto, el resultado de este ejemplo será la visualización de "hello", en la consola. En efecto, se ignora la llamada a next después del método complete.

También es posible utilizar el método error. Este método va a desencadenar un callback de error del observable. Una vez que se produce un error, si este no se trata (con el operador catch visto anteriormente), el observable pasa...