Skip to content

Latest commit

 

History

History
162 lines (106 loc) · 9.56 KB

File metadata and controls

162 lines (106 loc) · 9.56 KB

Capítulo 8 Angular HTTP

El método provideHttpClient expone varios servicios de Angular que podemos usar para manejar la comunicación HTTP asíncrona. El más básico es el servicio HttpClient, que proporciona una API robusta y abstrae todas las operaciones requeridas para manejar conexiones asíncronas a través de los siguientes métodos HTTP:

  • get: Realiza una operación GET para obtener datos.
  • post: Realiza una operación POST para añadir nuevos datos.
  • put / patch: Realiza una operación PUT/PATCH para actualizar datos existentes.
  • delete: Realiza una operación DELETE para eliminar datos existentes.

Los métodos HTTP anteriores constituyen las operaciones principales para las aplicaciones de Crear, Leer, Actualizar, Eliminar (CRUD).

Configuración de una API de backend

Una aplicación web CRUD normalmente se conecta a un servidor y utiliza una API de backend HTTP para realizar operaciones sobre los datos. Obtiene datos existentes, los actualiza, crea nuevos datos o los elimina.

En un escenario del mundo real, lo más probable es que interactúes con un servicio de API de backend real a través de HTTP. En este libro, utilizaremos una API falsa llamada Fake Store API.

La Fake Store API es una API REST de backend disponible en línea que puedes usar cuando necesites datos falsos para una aplicación web de comercio electrónico o tienda online. Puede gestionar productos, carritos de compra y usuarios disponibles en formato JSON. Expone los siguientes endpoints principales:

  • products: Gestiona un conjunto de artículos de producto.
  • cart: Gestiona el carrito de compras de un usuario.
  • user: Gestiona una colección de usuarios de la aplicación.
  • login: Maneja la autenticación de usuarios.

Manejo de datos CRUD en Angular

Las aplicaciones CRUD son ampliamente utilizadas en el mundo Angular. Difícilmente encontrarás alguna aplicación web que no siga este patrón. Angular hace un gran trabajo al soportar este tipo de aplicación al proporcionar el servicio HttpClient. En esta sección, exploraremos el cliente HTTP de Angular interactuando con el endpoint de productos de la Fake Store API.

Obtención de datos a través de HTTP

La clase ProductListComponent utiliza la clase ProductsService para obtener y mostrar los datos del producto. Los datos están actualmente codificados en la propiedad products de la clase ProductsService. En este commit, modificaremos nuestra aplicación Angular para trabajar con datos en vivo de la Fake Store API.

Modificación de datos a través de HTTP

La modificación de datos en una aplicación CRUD generalmente se refiere a añadir nuevos datos y a actualizar o eliminar datos existentes. Para demostrar cómo implementar dicha funcionalidad en una aplicación Angular usando el cliente HTTP, haremos los siguientes cambios en nuestra aplicación:

  • Crear un componente Angular para añadir nuevos productos.
  • Modificar el componente de detalle del producto para cambiar el precio de un producto existente.
  • Añadir un botón en el componente de detalle del producto para eliminar un producto existente.

Ya hemos mencionado que ninguna operación HTTP persiste datos físicamente en la Fake Store API, por lo que necesitamos implementar un mecanismo de caché local para nuestros datos de productos e interactuar directamente con él en el servicio de productos. En una aplicación real el backend tendría endpoints esto no ocurriría ya que tendríamos métodos para realizar todas las operaciones del CRUD necesarias.

No necesitamos desuscribirnos cuando interactuamos con el cliente HTTP de Angular porque el framework lo hará automáticamente por nosotros.

El método patch debe usarse cuando queremos actualizar solo un subconjunto de un objeto, mientras que el método put interactúa con todas las propiedades del objeto. En este caso, no queremos actualizar el título del producto, por lo que usamos el método patch. Ambos métodos aceptan el endpoint de la API y el objeto que queremos actualizar como parámetros.

Variables reactivas con BehaviorSubject

Para conseguir que cuando se cree un producto nuevo o se actualice un precio, se ordenen se ha usado BehaviorSubject. Este es un tipo especial de Subject. Vamos a explicar ambos conceptos.

Un Subject en RxJS es un tipo especial de Observable que también actúa como Observer.

Características principales:

  • Multidifusión: Todos los suscriptores reciben los mismos valores emitidos.
  • Bidireccionalidad: Puede recibir datos (como Observer) y emitirlos (como Observable).
  • Emisión manual: Los valores se emiten usando .next(valor). También se pueden emitir errores (.error) o completar el flujo (.complete).
  • No almacena valores previos: Solo entrega a cada suscriptor los valores emitidos después de su suscripción.

Ejemplo básico:

import { Subject } from 'rxjs';

const subject = new Subject<number>();

subject.subscribe(value => console.log('A:', value));
subject.next(1); // A: 1

subject.subscribe(value => console.log('B:', value));
subject.next(2); // A: 2, B: 2

// El primer suscriptor recibe 1 y 2.
// El segundo suscriptor solo recibe 2, porque se suscribió después del 1.

BehaviorSubject es un tipo especial de Subject en RxJS que:

  • Requiere un valor inicial al crearse.
  • Siempre mantiene el valor más reciente emitido.
  • Cuando un nuevo suscriptor se suscribe, recibe inmediatamente el último valor emitido, aunque se haya suscrito después de emisiones previas.
  • Puedes actualizar su valor usando .next(valor), y todos los suscriptores recibirán ese nuevo valor.

Ejemplo básico de uso:

import { BehaviorSubject } from 'rxjs';

const subject = new BehaviorSubject<number>(0); // Valor inicial: 0

subject.subscribe(value => console.log('Subscripción A:', value)); // Imprime 0

subject.next(1); // Imprime 1 en Subscripción A
subject.next(2); // Imprime 2 en Subscripción A

subject.subscribe(value => console.log('Subscripción B:', value)); // Imprime 2 en Subscripción B

subject.next(3); // Imprime 3 en Subscripción A y B

// Salida:
// Subscripción A: 0
// Subscripción A: 1
// Subscripción A: 2
// Subscripción B: 2
// Subscripción A: 3
// Subscripción B: 3

Variables reactivas con Signals

Podemos conseguir reactividad con signals. En este caso se ha convertido el Observable products del servicio en un Signal, lo que permite que los componentes se actualicen automáticamente cuando cambian los productos. Observe que el único método que devuelve un Signal es getProducts(), el resto devuelve una promesa ya que no se ha considerado que se necesite un comportamiento reactivo.

No obstante, todavía persisten dos problemas:

  • Cuando se actualiza el precio de un producto, se coloca correctamente pero el precio seleccionado se mantiene en el valor anterior.
  • Cuando se elimina un producto, el producto permanece seleccionado.

Autenticación y autorización con HTTP

La API de Fake Store proporciona un endpoint para autenticar usuarios. Contiene un método de inicio de sesión que acepta un nombre de usuario y una contraseña como parámetros y devuelve un token de autenticación. Usaremos el token de autenticación en nuestra aplicación para diferenciar entre un usuario que ha iniciado sesión y un invitado.

Usaremos un nuevo servicio llamado AuthService para manejar la autenticación:

ng generate service auth

También creamos un componente:

ng generate component auth

Finalmente, protegemos el botón Add to cart en el componente ProductDetailComponent. Este botón va a requerir estar autenticado para poder añadir un producto al carrito. En una aplicación real, habría que proteger otras funcionalidades como la modificación de productos. Además, no es suficiente con realizar el proceso de autorización en el cliente, ya que un usuario malintencionado podría modificar el código del cliente para realizar acciones no autorizadas. Por lo tanto, es importante implementar la autorización también en el servidor.

Autorización de solicitudes HTTP

La API de Fake Store no requiere autorización al comunicarse con sus endpoints. Sin embargo, supongamos que estamos trabajando con una API de backend que espera que todas las solicitudes HTTP contengan un token de autenticación utilizando encabezados HTTP. Un patrón común en las aplicaciones web es incluir el token en un encabezado de Autorización. Podemos usar encabezados HTTP en una aplicación Angular importando la clase HttpHeaders del espacio de nombres @angular/common/http y modificando nuestros métodos en consecuencia.

HTTP Interceptors

Habitualmente necesitaremos pasar el token de autenticación en todos los métodos de la clase ProductsService. Tendríamos que ir a cada uno de ellos y escribir el mismo código repetidamente. Nuestro código podría volverse rápidamente desordenado y difícil de probar. Afortunadamente, el cliente HTTP de Angular tiene otra característica que podemos usar para ayudarnos en tal situación, llamada interceptors. Un interceptor HTTP es un servicio de Angular que intercepta las solicitudes y respuestas HTTP que pasan a través del cliente HTTP de Angular. Se puede usar en los siguientes escenarios:

  • Cuando queremos pasar encabezados HTTP personalizados en cada solicitud, como un token de autenticación
  • Cuando queremos mostrar un indicador de carga mientras esperamos una respuesta del servidor
  • Cuando queremos proporcionar un mecanismo de registro para cada comunicación HTTP

Para ello, se crea un interceptor:

ng generate interceptor auth