Gestión de Datos y Servicios

Capítulo 3: Gestión de Datos y Servicios

Compartir

Introducción: La gestión de datos y servicios es esencial en las aplicaciones Angular. En este capítulo, exploraremos cómo crear servicios, inyectar dependencias, obtener datos de una API externa y manejar observables para gestionar datos asincrónicos.

3.1. Creación de servicios

  • ¿Qué son los servicios en Angular? Los servicios son una parte fundamental de la arquitectura de Angular. Son clases que se utilizan para encapsular la lógica de la aplicación y proporcionar funcionalidades compartidas entre componentes. Los servicios se utilizan comúnmente para gestionar operaciones de red, interacción con APIs, almacenamiento en caché de datos y más.

Un servicio en Angular es una clase que se utiliza para realizar tareas comunes o compartir datos y funcionalidad entre componentes. Aquí tienes un ejemplo simple de un servicio en Angular que proporciona un conjunto de funciones para administrar una lista de tareas:

task.service.ts (Servicio de tareas):

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class TaskService {
  private tasks: string[] = [];

  addTask(task: string) {
    this.tasks.push(task);
  }

  getTasks() {
    return this.tasks;
  }

  removeTask(task: string) {
    const index = this.tasks.indexOf(task);
    if (index !== -1) {
      this.tasks.splice(index, 1);
    }
  }
}

En este ejemplo:

  • El servicio TaskService tiene tres métodos: addTask, getTasks y removeTask. Estos métodos permiten agregar una tarea a la lista, obtener la lista de tareas y eliminar una tarea específica.
  • El servicio está decorado con @Injectable y se proporciona en el nivel raíz (providedIn: 'root'), lo que significa que Angular lo administrará automáticamente como un servicio singleton accesible en toda la aplicación.

Luego, puedes inyectar este servicio en cualquier componente que lo necesite. Por ejemplo, si tienes un componente TaskListComponent que muestra y gestiona tareas, puedes inyectar el servicio de la siguiente manera:

task-list.component.ts (Componente de lista de tareas):

import { Component } from '@angular/core';
import { TaskService } from './task.service';

@Component({
  selector: 'app-task-list',
  templateUrl: './task-list.component.html',
})
export class TaskListComponent {
  tasks: string[] = [];

  constructor(private taskService: TaskService) {
    this.tasks = taskService.getTasks();
  }

  addTask(newTask: string) {
    this.taskService.addTask(newTask);
  }

  removeTask(task: string) {
    this.taskService.removeTask(task);
  }
}

En este ejemplo, el componente TaskListComponent utiliza el servicio TaskService para obtener y gestionar las tareas. Puedes seguir un patrón similar para utilizar servicios en Angular y compartir datos o funcionalidad en toda la aplicación.

  • Creación de servicios personalizados Puedes crear tus propios servicios personalizados en Angular. Estos servicios se generan típicamente con Angular CLI o se crean manualmente. Los servicios encapsulan la lógica relacionada con un área específica de la aplicación.

Aquí tienes un ejemplo de cómo crear un servicio personalizado en Angular. Supongamos que deseas crear un servicio llamado UserService que gestione la información de usuarios en tu aplicación.

user.service.ts (Servicio de usuarios):

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private users: string[] = [];

  constructor() {
    // Inicializamos el servicio con algunos usuarios de ejemplo
    this.users = ['Usuario 1', 'Usuario 2', 'Usuario 3'];
  }

  getUsers() {
    return this.users;
  }

  addUser(user: string) {
    this.users.push(user);
  }

  removeUser(user: string) {
    const index = this.users.indexOf(user);
    if (index !== -1) {
      this.users.splice(index, 1);
    }
  }
}

En este ejemplo:

  • Creamos un servicio llamado UserService con tres métodos: getUsers, addUser y removeUser. Estos métodos permiten obtener la lista de usuarios, agregar un usuario y eliminar un usuario.
  • El servicio está decorado con @Injectable y se proporciona en el nivel raíz (providedIn: 'root'), lo que significa que Angular lo administrará automáticamente como un servicio singleton accesible en toda la aplicación.
  • En el constructor del servicio, inicializamos la lista de usuarios con algunos usuarios de ejemplo.

Una vez que hayas creado este servicio, puedes inyectarlo en cualquier componente que lo necesite. Por ejemplo, si tienes un componente UserListComponent que muestra y gestiona la lista de usuarios, puedes inyectar el servicio de la siguiente manera:

user-list.component.ts (Componente de lista de usuarios):

import { Component } from '@angular/core';
import { UserService } from './user.service';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
})
export class UserListComponent {
  users: string[] = [];

  constructor(private userService: UserService) {
    this.users = userService.getUsers();
  }

  addUser(newUser: string) {
    this.userService.addUser(newUser);
  }

  removeUser(user: string) {
    this.userService.removeUser(user);
  }
}

En este ejemplo, el componente UserListComponent utiliza el servicio UserService para obtener y gestionar la lista de usuarios. Este es un patrón común para crear y utilizar servicios personalizados en Angular para administrar datos y funcionalidad en tu aplicación.

  • Inyección de dependencias En Angular, la inyección de dependencias es el proceso de proporcionar instancias de servicios a componentes que los necesitan. Angular maneja la inyección de dependencias de manera automática y asegura que las instancias de servicios estén disponibles cuando se solicitan.

La inyección de dependencias es un patrón fundamental en Angular que se utiliza para proporcionar instancias de servicios u otras dependencias a los componentes. Aquí tienes un ejemplo de inyección de dependencias en Angular.

Supongamos que tenemos un servicio llamado LoggerService que se utiliza para registrar mensajes en la consola, y un componente llamado UserService que necesita utilizar este servicio para registrar eventos. Primero, creamos el servicio LoggerService.

logger.service.ts (Servicio de registro):

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class LoggerService {
  log(message: string) {
    console.log(message);
  }
}

Ahora, en el componente UserService, podemos inyectar el servicio LoggerService y utilizarlo para registrar eventos. Asegúrate de que el servicio LoggerService esté registrado en el módulo de la aplicación o en el nivel raíz.

user.service.ts (Componente de usuario que inyecta el servicio de registro):

import { Injectable } from '@angular/core';
import { LoggerService } from './logger.service';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  constructor(private logger: LoggerService) {}

  addUser(username: string) {
    this.logger.log(`Usuario ${username} agregado.`);
    // Lógica para agregar el usuario...
  }
}

En este ejemplo:

  • El servicio LoggerService se inyecta en el constructor del componente UserService. La inyección de dependencias se realiza automáticamente por Angular.
  • El componente UserService utiliza el servicio LoggerService para registrar eventos cuando se agrega un usuario.
  • La inyección de dependencias permite que el componente UserService obtenga una instancia del servicio `LoggerService sin necesidad de crearlo manualmente.

Este ejemplo demuestra cómo se utiliza la inyección de dependencias en Angular para proporcionar y utilizar servicios dentro de los componentes. Angular se encarga de la creación de instancias y la gestión de dependencias, lo que hace que la aplicación sea más modular y mantenible.

3.2. Obtención de datos de una API

  • Consumir datos de una API externa en Angular Una parte común de muchas aplicaciones es obtener datos de una API externa, como un servidor web o una base de datos. Angular proporciona las herramientas para realizar solicitudes HTTP y manejar las respuestas de una API.
  • Hacer solicitudes HTTP con HttpClient Angular proporciona el módulo HttpClient que simplifica la realización de solicitudes HTTP. Puedes utilizar este módulo para realizar solicitudes GET, POST, PUT, DELETE y más.
  • Manejo de respuestas de API Cuando obtienes datos de una API, es importante manejar las respuestas correctamente. Puedes suscribirte a observables para recibir datos y manejar errores o situaciones inesperadas.

Aquí tienes un ejemplo de cómo consumir datos de una API externa en Angular, realizar solicitudes HTTP con HttpClient y manejar las respuestas de la API. En este ejemplo, utilizaremos una API pública de prueba llamada JSONPlaceholder para obtener una lista de publicaciones (posts).

  1. Configuración del módulo y servicio:

Primero, asegúrate de importar el módulo HttpClientModule en tu aplicación. Puedes hacerlo en el archivo de tu módulo principal (por lo general, app.module.ts).

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  declarations: [...],
  imports: [HttpClientModule],
  bootstrap: [...]
})
export class AppModule { }

Luego, crea un servicio para realizar las solicitudes HTTP. En este caso, llamaremos al servicio PostService.

post.service.ts (Servicio para consumir la API):

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PostService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) {}

  getPosts(): Observable<any[]> {
    return this.http.get<any[]>(this.apiUrl);
  }
}

Consumir datos de la API en un componente:

Ahora, puedes consumir los datos de la API en un componente. Por ejemplo, creemos un componente llamado PostListComponent para mostrar las publicaciones obtenidas de la API.

post-list.component.ts (Componente para mostrar las publicaciones):

import { Component, OnInit } from '@angular/core';
import { PostService } from './post.service';

@Component({
  selector: 'app-post-list',
  templateUrl: './post-list.component.html',
})
export class PostListComponent implements OnInit {
  posts: any[] = [];

  constructor(private postService: PostService) {}

  ngOnInit() {
    this.postService.getPosts().subscribe((data) => {
      this.posts = data;
    });
  }
}

Mostrar los datos en la plantilla:

Finalmente, muestra los datos obtenidos de la API en la plantilla del componente.

post-list.component.html (Plantilla para mostrar las publicaciones):

<h2>Listado de Publicaciones</h2>
<ul>
  <li *ngFor="let post of posts">
    <strong>{{ post.title }}</strong>
    <p>{{ post.body }}</p>
  </li>
</ul>

En este ejemplo:

  • El servicio PostService realiza una solicitud HTTP GET para obtener datos de la API JSONPlaceholder.
  • En el componente PostListComponent, se suscribe a la respuesta de la solicitud HTTP y almacena los datos en la propiedad posts.
  • La plantilla HTML muestra las publicaciones utilizando la directiva *ngFor para iterar a través de las publicaciones en la lista.

Este es un ejemplo básico de cómo consumir datos de una API externa en Angular utilizando el servicio HttpClient y manejar las respuestas de la API en un componente. Ten en cuenta que debes importar HttpClientModule y proporcionar el servicio en el módulo de la aplicación. También es importante manejar errores y realizar tareas adicionales según tus necesidades en una aplicación real.

3.3. Manejo de observables

  • ¿Qué son los observables en Angular? Los observables son una parte clave de la programación reactiva en Angular. Representan secuencias de eventos o valores que se pueden observar a lo largo del tiempo. Los observables se utilizan ampliamente para manejar datos asincrónicos, como respuestas de API o eventos de usuario.
  • Utilización de observables para datos asincrónicos Aprenderás cómo utilizar observables en Angular para manejar datos asincrónicos. Puedes suscribirte a observables para recibir notificaciones cuando se emiten nuevos valores o eventos.
  • Manejo de errores y finalización de observables También aprenderás a manejar errores que puedan ocurrir al realizar solicitudes HTTP o al trabajar con observables. Además, verás cómo completar y liberar recursos asociados con observables cuando ya no son necesarios.

Aquí tienes un ejemplo de cómo utilizar observables en Angular para manejar datos asincrónicos y cómo manejar errores y finalización de observables. En este ejemplo, utilizaremos observables para realizar una solicitud HTTP a una API y gestionar la respuesta.

  1. Creación de un servicio y solicitud HTTP:

Primero, crearemos un servicio llamado DataService para realizar una solicitud HTTP a una API. Asegúrate de importar HttpClient y Observable de rxjs.

data.service.ts (Servicio de datos):

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) {}

  fetchData(): Observable<any[]> {
    return this.http.get<any[]>(this.apiUrl);
  }
}

Consumir el servicio en un componente:

A continuación, crearemos un componente llamado DataComponent que consume el servicio DataService y maneja la respuesta asincrónica.

data.component.ts (Componente para consumir datos):

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
import { catchError } from 'rxjs/operators';
import { of } from 'rxjs';

@Component({
  selector: 'app-data',
  templateUrl: './data.component.html',
})
export class DataComponent implements OnInit {
  data: any[] = [];
  error: string = '';

  constructor(private dataService: DataService) {}

  ngOnInit() {
    this.dataService
      .fetchData()
      .pipe(
        catchError((error) => {
          this.error = 'Error al cargar datos.';
          return of([]);
        })
      )
      .subscribe(
        (response) => {
          this.data = response;
        },
        (error) => {
          this.error = 'Error en la solicitud HTTP.';
        }
      );
  }
}

Manejo de observables en la plantilla:

Por último, mostraremos los datos obtenidos de la API y cualquier mensaje de error en la plantilla.

data.component.html (Plantilla para mostrar datos y errores):

<h2>Datos Asincrónicos</h2>
<ul *ngIf="data.length > 0; else noData">
  <li *ngFor="let item of data">
    {{ item.title }}
  </li>
</ul>
<ng-template #noData>
  <p>No hay datos disponibles.</p>
</ng-template>
<div *ngIf="error">{{ error }}</div>

En este ejemplo:

  • El servicio DataService realiza una solicitud HTTP y devuelve un observable que emite la respuesta de la API.
  • En el componente DataComponent, utilizamos el método fetchData() del servicio para obtener datos asincrónicos.
  • Utilizamos operadores de rxjs como catchError para manejar errores y of para emitir un valor predeterminado cuando se produce un error en la solicitud HTTP.
  • En la plantilla HTML, mostramos los datos obtenidos si están disponibles y mostramos un mensaje de error en caso de que ocurra un error.

Este ejemplo demuestra cómo utilizar observables en Angular para manejar datos asincrónicos, manejar errores y finalización de observables al realizar solicitudes HTTP a una API externa. Ten en cuenta que puedes adaptar este patrón para trabajar con otras fuentes de datos asincrónicos en tu aplicación.

3.4. Ejemplos Prácticos:

  • Creación de un servicio en Angular Te guiaré a través del proceso de creación de un servicio personalizado en Angular que encapsula la lógica para interactuar con una API externa. Verás cómo generar un servicio con Angular CLI y cómo agregar métodos para realizar solicitudes HTTP.
  • Inyección de dependencias de servicios en componentes Aprenderás a inyectar servicios en componentes utilizando la inyección de dependencias de Angular. Esto permitirá que los componentes accedan a las funcionalidades proporcionadas por el servicio.
  • Obtención de datos de una API externa Verás cómo utilizar HttpClient para hacer solicitudes HTTP a una API externa y cómo manejar las respuestas. Esto incluye la suscripción a observables y el manejo de errores.
  • Manejo de datos asincrónicos con observables Aprenderás a utilizar observables para manejar datos asincrónicos y a manejar situaciones como la carga de datos en una aplicación y la actualización de la vista en respuesta a eventos de datos.

Aquí tienes un ejemplo de cómo crear un servicio en Angular, realizar la inyección de dependencias en componentes, obtener datos de una API externa y manejar los datos asincrónicos con observables. En este ejemplo, utilizaremos un servicio llamado PostService para obtener una lista de publicaciones desde una API externa.

  1. Creación del servicio:

Primero, crea el servicio PostService que se encargará de realizar la solicitud HTTP para obtener datos de la API externa.

post.service.ts (Servicio para obtener publicaciones):

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class PostService {
  private apiUrl = 'https://jsonplaceholder.typicode.com/posts';

  constructor(private http: HttpClient) {}

  getPosts(): Observable<any[]> {
    return this.http.get<any[]>(this.apiUrl);
  }
}

Inyección del servicio en un componente:

Ahora, crearemos un componente llamado PostListComponent que inyecta el servicio PostService para obtener y mostrar las publicaciones.

post-list.component.ts (Componente para mostrar las publicaciones):

import { Component, OnInit } from '@angular/core';
import { PostService } from './post.service';

@Component({
  selector: 'app-post-list',
  templateUrl: './post-list.component.html',
})
export class PostListComponent implements OnInit {
  posts: any[] = [];

  constructor(private postService: PostService) {}

  ngOnInit() {
    this.postService.getPosts().subscribe((data) => {
      this.posts = data;
    });
  }
}

Plantilla para mostrar los datos:

Por último, en la plantilla del componente PostListComponent, mostraremos los datos obtenidos de la API.

post-list.component.html (Plantilla para mostrar las publicaciones):

<h2>Listado de Publicaciones</h2>
<ul>
  <li *ngFor="let post of posts">
    <strong>{{ post.title }}</strong>
    <p>{{ post.body }}</p>
  </li>
</ul>

En este ejemplo:

  • El servicio PostService realiza una solicitud HTTP para obtener las publicaciones desde la API externa y devuelve un observable que emite la respuesta.
  • En el componente PostListComponent, se inyecta el servicio PostService y se suscribe al observable para obtener los datos de las publicaciones.
  • La plantilla HTML muestra las publicaciones utilizando la directiva *ngFor para iterar a través de las publicaciones en la lista.

Este ejemplo demuestra cómo crear un servicio, realizar la inyección de dependencias en un componente, obtener datos de una API externa y manejar datos asincrónicos con observables en Angular. Ten en cuenta que debes importar HttpClientModule y proporcionar el servicio PostService en el módulo de la aplicación para que funcione correctamente.

Este capítulo te proporcionará las habilidades necesarias para gestionar datos y servicios en aplicaciones Angular, incluyendo cómo crear servicios personalizados, interactuar con APIs externas y manejar datos asincrónicos utilizando observables. Los ejemplos prácticos te ayudarán a aplicar estos conceptos en situaciones reales.


Compartir

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *