TUP_4C_DABD_TEO_U3_ComunicacionNavegacion.pdf

Full Transcript

DISEÑO Y ADMINISTRACIÓN DE BASE DE DATOS Unidad Temática N°3: Comunicación y Navegación Material de Estudio 2° Año – 4° Cuatrimestre HTTP 2 Petición HTTP...

DISEÑO Y ADMINISTRACIÓN DE BASE DE DATOS Unidad Temática N°3: Comunicación y Navegación Material de Estudio 2° Año – 4° Cuatrimestre HTTP 2 Petición HTTP........................................................................................................... 2 Asincronismo............................................................................................................. 3 Observables and Subscriptions................................................................................. 3 ¿Qué es?................................................................................................................... 4 Características claves:.............................................................................................. 4 Usos más comunes:.................................................................................................. 4 HttpClient................................................................................................................... 6 Liberación de recursos.............................................................................................. 9 Otras solicitudes HTTP........................................................................................... 10 POST Request:................................................................................................. 10 PUT Request:................................................................................................... 10 DELETE Request:............................................................................................ 10 Async Pipe.............................................................................................................. 11 Subject & BehaviorSubject...................................................................................... 12 Operadores RxJS 15 Operador map......................................................................................................... 15 Operador filter......................................................................................................... 16 Operador switchMap............................................................................................... 17 Operador mergeMap............................................................................................... 19 Operador combineLatest......................................................................................... 20 Routing 22 Configuración y uso................................................................................................. 22 Navegación desde componentes TypeScript.......................................................... 23 Obtención valores por QueryString......................................................................... 25 Bibliografía 27 DABD Material de Estudio – U3 Pág. 1 HTTP Petición HTTP Una petición HTTP (Hypertext Transfer Protocol) es un mensaje que un cliente (como un navegador web) envía a un servidor web para solicitar algún tipo de recurso o realizar una acción en el servidor. Las peticiones HTTP son el fundamento de la comunicación en la World Wide Web y se utilizan para acceder a sitios web, obtener datos de servidores, enviar datos a servidores y realizar otras operaciones en línea. Una solicitud HTTP generalmente consta de los siguientes elementos: Verbo HTTP: Este es un método que indica la acción que se debe realizar en el servidor. Los verbos HTTP más comunes son: o GET: Para solicitar datos del servidor. o POST: Para enviar datos al servidor, como al enviar formularios. o PUT: Para actualizar un recurso en el servidor. o DELETE: Para eliminar un recurso en el servidor. o Otros, como HEAD, OPTIONS, PATCH, etc. URL (Uniform Resource Locator): La URL indica la dirección del recurso que se desea acceder en el servidor. Esto puede ser una página web, un archivo, una API, etc. Encabezados HTTP: Los encabezados son metadatos adicionales que acompañan a la solicitud y proporcionan información adicional sobre la solicitud. Los encabezados pueden incluir información como el tipo de contenido que se acepta, cookies, información de autenticación, y más. Cuerpo de la solicitud (opcional): En algunas solicitudes, como las solicitudes POST o PUT, se puede incluir un cuerpo que contiene los datos que se envían al servidor. Por ejemplo, al enviar datos de un formulario. Una vez que el servidor recibe una solicitud HTTP, procesa la solicitud, toma la acción apropiada según el verbo y la URL, y luego devuelve una respuesta HTTP al cliente. La respuesta también incluye un código de estado que indica el resultado de la solicitud (por ejemplo, 200 para éxito, 404 para recurso no encontrado, 500 para error interno del servidor, etc.), encabezados de respuesta y, en muchas ocasiones, un cuerpo de respuesta que contiene los datos solicitados o información adicional. DABD Material de Estudio – U3 Pág. 2 Asincronismo Se refiere a un estilo de programación en el cual las tareas no se ejecutan de manera secuencial, una después de la otra, sino que pueden ejecutarse de manera concurrente y en un orden no determinista. Esto significa que las tareas pueden comenzar y finalizar en momentos diferentes y en un orden que puede variar. El asincronismo es especialmente útil en situaciones en las que se pueden producir operaciones lentas o bloqueantes, como lecturas/escrituras de archivos, solicitudes a servidores remotos o cualquier operación que pueda llevar tiempo. En lugar de esperar a que una tarea se complete antes de continuar con la siguiente, el programa puede continuar ejecutando otras tareas y responder a eventos a medida que se produzcan. En muchos lenguajes de programación, se utilizan conceptos y mecanismos para implementar la asincronía, como: Hilos (Threads): Los hilos son subprocesos de ejecución dentro de un programa que pueden ejecutarse de manera concurrente. Los programas que utilizan hilos pueden realizar múltiples tareas al mismo tiempo. Callbacks: Los callbacks son funciones que se pasan como argumentos a otras funciones y se ejecutan cuando se completa una operación asincrónica. Son comunes en JavaScript y se utilizan en la programación basada en eventos. Promesas (Promises): Las promesas son objetos que representan un valor que puede estar disponible ahora, en el futuro o nunca. Se utilizan para manejar operaciones asincrónicas en un estilo más estructurado y legible. Async/Await: Este es un enfoque más moderno y legible para trabajar con código asincrónico en muchos lenguajes, incluyendo JavaScript y Python. Permite escribir código asincrónico de manera similar a las operaciones síncronas, lo que facilita su comprensión. Observables and Subscriptions Los observables son una parte fundamental de la programación reactiva y se utilizan comúnmente en aplicaciones Angular para gestionar flujos de datos asíncronos. Los observables proporcionan una forma elegante de trabajar con secuencias de datos que pueden cambiar con el tiempo. DABD Material de Estudio – U3 Pág. 3 ¿Qué es? Un observable es un objeto que representa una secuencia de datos asíncronos. Estos datos pueden ser eventos, resultados de solicitudes HTTP, cambios en propiedades, o cualquier otra fuente de información que cambie con el tiempo. Los observables permiten observar (escuchar) estos cambios y reaccionar a ellos de manera asincrónica. Características claves: Asincronía: Los observables se utilizan para manejar operaciones asíncronas, lo que significa que no bloquean la ejecución del programa mientras esperan resultados. Emisión de datos: Los observables emiten datos a lo largo del tiempo. Pueden emitir varios valores en una secuencia. Manejo de errores: Los observables permiten manejar errores que pueden ocurrir durante la ejecución de una operación asíncrona. Completado: Un observable puede completarse, lo que significa que no emitirá más datos y se dará por terminado. Usos más comunes: Solicitudes HTTP: Cuando haces una solicitud HTTP utilizando el módulo HttpClient, obtienes un observable como respuesta. Puedes suscribirte a este observable para recibir los datos de respuesta. Manejo de eventos: Puedes usar observables para manejar eventos del usuario, como clics de botones o entradas de formularios, utilizando la API de RxJS en Angular. Actualizaciones en tiempo real: Si trabajas con aplicaciones en tiempo real, como chat en vivo o paneles de control, los observables son útiles para recibir actualizaciones automáticas de los datos del servidor. Manejo de datos reactivos: Los observables son una parte fundamental del enfoque reactivo en Angular, que permite construir interfaces de usuario altamente responsivas y dinámicas. DABD Material de Estudio – U3 Pág. 4 En Angular, los observables se implementan utilizando RxJS (Reactive Extensions for JavaScript), una biblioteca que proporciona una amplia gama de operadores para transformar y combinar observables. En Angular, las suscripciones se utilizan para observar (escuchar) los valores emitidos por un observable. Un observable es una secuencia de eventos o datos que pueden cambiar con el tiempo. Para interactuar con los valores emitidos por un observable, debes suscribirte a él. Ejemplo: Crear un Observable: import { Observable, interval } from 'rxjs'; const intervalo = interval(1000); // Emite un valor cada segundo Suscribirse al Observable: Una vez que tienes un observable, puedes suscribirte a él utilizando el método subscribe(). Este método acepta uno o más argumentos de devolución de llamada (funciones) que se ejecutarán cuando el observable emita valores, errores o se complete. Por lo general, se proporcionan tres devoluciones de llamada: next, error y complete. Sin embargo, solo next es obligatorio. import { Observable, interval } from 'rxjs'; const suscripcion = intervalo.subscribe( (valor) => { console.log('Valor emitido', valor); // Realiza acciones con el valor emitido }, (error) => { console.error('Error', error); // Realiza acciones para manejar el error }, () => { console.log('Observable completado'); // Realiza acciones cuando el observable se completa }, ); La función next se ejecutará cada vez que el observable emita un valor. La función error se ejecutará si ocurre un error en el observable. La función complete se ejecutará cuando el observable se complete y ya no emita más valores. DABD Material de Estudio – U3 Pág. 5 Desuscribirse del Observable: Es importante desuscribirse de un observable cuando ya no necesitas observar sus valores para evitar pérdidas de memoria y problemas de rendimiento. Para hacerlo, puedes almacenar la suscripción en una variable y luego llamar al método unsubscribe() cuando desees cancelar la suscripción. suscripcion.unsubscribe(); // Cancela la suscripción al observable También puedes utilizar el operador takeUntil o el método pipe para gestionar automáticamente la desuscripción en ciertas condiciones. HttpClient Para realizar solicitudes HTTP en una aplicación Angular, puedes utilizar el módulo HttpClient de Angular, que proporciona una forma fácil de interactuar con servicios web y API. Importar el módulo HttpClient: En tu archivo de módulo, generalmente llamado app.module.ts, asegúrate de importar el módulo HttpClientModule desde @angular/common/http y agregarlo a la lista de imports del módulo: import { NgModule } from '@angular/core'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ imports: [ // … HttpClientModule ], // … }) export class AppModule { } DABD Material de Estudio – U3 Pág. 6 Inyectar HttpClient en tu servicio o componente: Para utilizar HttpClient en un servicio o componente, es necesario inyectarlo y en angular se puede hacer mediante el constructor. import { HttpClient } from '@angular/common/http'; @Injectable({ provideIn: root’ }) export class NuevoService { constructor(private http: HttpClient) { } obtenerDatos(): Observable { return this.http.get('https://api.example.com/data'); } } Manejar la respuesta: Para obtener la respuesta de la solicitud HTTP desde el componente es necesario suscribirse a dicho método el cual una vez que la API responda emitirá la respuesta. Ejemplo: Inyectar servicio en componente y realizar la llamada: import { OnInit } from '@angular/core'; import { NuevoService } from './nuevo.service.ts; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) export class PruebaComponent implements OnInit { listado: Producto[] = []; constructor(private servicio: NuevoService) { } ngOnInit(): void { this.servicio.obtenerDatos().subscribe( next: (response: Producto[]) => { this.listado = response; // Aquí puedes realizar cualquier otra acción con los datos recibidos }, error: (error: Error) => { console.error(error); // Aquí puedes realizar el manejo del error como se desee, // en este caso se imprime un mensaje en la consola del navegador } ); } } DABD Material de Estudio – U3 Pág. 7 import { OnInit } from '@angular/core'; import { NuevoService } from './nuevo.service.ts; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) export class PruebaComponent implements OnInit { listado: Producto[] = []; constructor(private servicio: NuevoService) { } ngOnInit(): void { this.servicio.obtenerDatos().subscribe( (response: Producto[]) => { this.listado = response; // Aquí puedes realizar cualquier otra acción con los datos recibidos }, (error) => { console.error(error); // Aquí puedes realizar el manejo del error como se desee, // en este caso se imprime un mensaje en la consola del navegador } ); } } Como se puede ver existen dos alternativas para el manejo de las respuestas al suscribirse a un Observable. La primera es la utilizada en el ejemplo de observables utilizando un intervalo y la segunda es una forma simplificada que no requiere la declaración de las funciones callback (next, error, complete). Otro punto interesante es que no es obligatorio implementar el manejo de los errores o la completitud de la notificación emitida por el Observable, aunque es una buena práctica manejar los escenarios de errores para ofrecer un buen feedback a los usuarios de nuestras aplicaciones. Una vez que se llama al servicio que hace la llamada a la API en caso de obtener una respuesta satisfactoria se carga el dicho resultado en una propiedad existente en el componente, en el ejemplo se asigna el arreglo de Productos proveniente de la API a la propiedad listado dentro del componente. DABD Material de Estudio – U3 Pág. 8 Liberación de recursos Es importante tener en cuenta la liberación de los recursos que utilizamos, como se mostró en el ejemplo del intervalo. Para cuando consumimos una API se puede realizar de la siguiente manera: import { Component, OnInit, OnDestroy } from '@angular/core'; import { Subscription } from 'rxjs'; import { NuevoService } from './nuevo.service.ts; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) export class PruebaComponent implements OnInit, OnDestroy { listado: Producto[] = []; private suscripciones = new Subscription(); constructor(private servicio: NuevoService) { } ngOnDestroy(): void { this.subscripciones.unsubscribe(); // Aquí se realiza la liberación de todas las suscripciones que hayan sido agregadas // a este objeto por lo que al destruirse el componente se liberará memoria. } ngOnInit(): void { this.subscripciones.add( this.servicio.obtenerDatos().subscribe( (response: Producto[]) => { this.listado = response; // Aquí puedes realizar cualquier otra acción con los datos recibidos }, (error) => { console.error(error); // Aquí puedes realizar el manejo del error como se desee, // en este caso se imprime un mensaje en la consola del navegador } ) ); } } DABD Material de Estudio – U3 Pág. 9 Otras solicitudes HTTP Se pueden utilizar los métodos proporcionados por HttpClient para realizar otras peticiones HTTP como(POST, PUT, DELETE, etc.). A continuación se muestran ejemplos de las más comunes: POST Request: export class NuevoService { constructor(private http: HttpClient) { } crear(body: Product): Observable { return this.http.post('https://api.example.com/data', body); } } PUT Request: export class NuevoService { constructor(private http: HttpClient) { } actualizar(body: Product): Observable { return this.http.put('https://api.example.com/data', body); } } DELETE Request: export class NuevoService { constructor(private http: HttpClient) { } borrar(body: Product): Observable { return this.http.delete('https://api.example.com/data'); } } DABD Material de Estudio – U3 Pág. 10 Async Pipe Se utiliza para simplificar la suscripción y desuscripción a observables en las plantillas de componentes. Este pipe facilita la presentación de datos asincrónicos, como resultados de solicitudes HTTP o valores de observables, en las plantillas de manera más limpia y eficiente. Ejemplo: import { Component } from '@angular/core'; import { Observable } from 'rxjs'; @Component({ selector: ’app-prueba’, template: ` {{ datos }} `, }) export class PruebaComponent { datosObservable: Observable; constructor() { // Inicializa datosObservable, por ejemplo, con una solicitud HTTP this.datosObservable = this.obtenerDatos(); } objeterDatos(): Observable { // Simulación de una solicitud HTTP return new Observable(observer => { setTimeout(() => { observer.next('Datos asincrónicos'); observer.complete(); }, 2000); }); } } En este ejemplo: Tenemos una propiedad datosObservable que es un observable que emite datos asincrónicos (simulados en este caso). En la plantilla, utilizamos el async pipe en el elemento para mostrar los datos asincrónicos. La expresión *ngIf="datosObservable | async as datos" espera a que datosObservable emita un valor y luego almacena ese valor en la variable datos para su uso dentro del. Cuando datosObservable emite datos, se muestran en la plantilla automáticamente debido al async pipe. No es necesario suscribirse manualmente al observable ni preocuparse por la desuscripción, ya que el DABD Material de Estudio – U3 Pág. 11 async pipe se encarga de eso de manera automática cuando se destruye el componente. El uso del async pipe es una práctica recomendada en Angular para manejar datos asincrónicos en las plantillas de manera más segura y sencilla, evitando problemas de fugas de memoria relacionados con la suscripción y la desuscripción manual de observables. Subject & BehaviorSubject Subject es una clase proporcionada por la librería RxJS que actúa como un observable y un observador al mismo tiempo. Un Subject se utiliza para crear flujos de datos que pueden ser observados por múltiples partes de una aplicación. Es una forma poderosa de comunicarse entre componentes y servicios en una aplicación. Hay varios tipos de Subject en RxJS, pero los dos más comunes son: Subject: Un Subject básico que actúa como un observador y un observable al mismo tiempo. Puedes usarlo para emitir valores y suscribirte a esos valores en múltiples partes de tu aplicación. BehaviorSubject: Un tipo especial de Subject que almacena el último valor emitido y lo emite inmediatamente a cualquier nuevo suscriptor. Esto significa que cuando te suscribes a un BehaviorSubject, obtendrás el valor más reciente inmediatamente, incluso si te suscribes después de que se haya emitido el valor. Ejemplo de un Subject basico: import { Component } from '@angular/core'; import { ComunicadorService } from './comunicador.service'; @Component({ selector: ’app-enviador’, template: ` Enviar Producto A Enviar Producto B `, }) DABD Material de Estudio – U3 Pág. 12 export class EnviadorComponent { // Creamos un Subject para enviar datos private productSubject = new Subject(); constructor(private comunicadorService: ComunicadorService) { } // Método para enviar datos al Subject enviarProducto(nombre: string) { this.comunicadorService.enviarMensaje(nombre); } } Servicio que hará de intermediario entre un componente y otro. import { Subject} from '@angular/core'; @Injectable({ provideIn: root’ }) export class ComunicadorService { // Creamos un Subject para enviar datos private productSubject = new Subject(); enviarDatos(nombre: string){ this.productSubject.next(nombre); } recibirDatos(){ return this.productSubject.asObservable(); } } Componente que recibe el mensaje: import { Component } from '@angular/core'; @Component({ selector: ’app-recibidor, template: ` Producto recibido: {{ valorRecibido }} `, }) export class RecibidorComponent class OnInit { valorRecibido: string; constructor(private comunicadorService: ComunicadorService) { } // Leer el observable que va a emitir el valor con el nombre del producto proveniente // de la emisión en el componente Enviador onInit(): void { this.comunicadorService.recibirDatos().subscribe(product => { this.valorRecibido = product; }); } } DABD Material de Estudio – U3 Pág. 13 Llamar a ambos componentes para que se muestren en nuestra aplicación: Comunicación entre Componentes con Subject Para el caso de BehaviorSubject la diferencia está en su creación ya que utiliza la clase BehaviorSubject la cual recibe en su constructor un valor obligatoriamente el cual va a ser el transmitido al suscribirse a este flujo de datos. A continuación, se muestra un ejemplo para la creación de un BehaviorSubject desde un servicio: import { BehaviorSubject } from '@angular/core'; @Injectable({ provideIn: root’ }) export class ComunicadorService { // Creamos un BehaviorSubject para enviar datos private productBehaviorSubject = new BehaviorSubject('Producto Inicial'); enviarDatos(nombre: string){ this.productBehaviorSubject.next(nombre); } recibirDatos(){ return this.productBehaviorSubject.asObservable(); } } La parte del consumo es exactamente igual que con un Subject con la salvedad de que se recibe un valor inicial. DABD Material de Estudio – U3 Pág. 14 Operadores RxJS Reactive Extensions for JavaScript es una librería que proporciona herramientas para trabajar con programación reactiva en JavaScript, lo que significa que te permite manejar flujos de datos asincrónicos de manera más eficiente y declarativa. Proporciona una amplia gama de operadores que permiten transformar, filtrar, combinar y manipular flujos de datos observables de manera elegante y funcional. Algunos ejemplos de operadores comunes incluyen map, filter, mergeMap, switchMap, combineLatest, entre otros. Para la utilización de los operadores es necesario importar la librería rxjs/operators y luego llamar al operador que se requiera utilizar. Operador map Se utiliza para transformar los valores emitidos por un observable en nuevos valores. Es una herramienta fundamental en la programación reactiva y se utiliza para realizar operaciones de mapeo en el flujo de datos observables. La función de mapeo se aplica a cada elemento que fluye a través del observable y produce un nuevo valor que se emitirá en el observable resultante. Es útil en diversas situaciones, como: Transformación de datos: Puede utilizarse para cambiar la forma o el tipo de datos emitidos por un observable. Por ejemplo, puedes convertir un flujo de datos de respuestas HTTP en un flujo de datos que solo contenga ciertos campos específicos de esas respuestas. Modificación de valores: Puedes aplicar operaciones matemáticas u otras transformaciones a los valores emitidos. Por ejemplo, puedes sumar un valor constante a cada número emitido. Adaptación de datos: Si tienes un flujo de datos con una estructura específica y necesitas adaptarlo para que sea compatible con otra parte de tu aplicación, el operador map puede ayudarte a hacer esa adaptación. Filtrado: Aunque el operador filter se utiliza específicamente para filtrar valores, el map también se puede usar para filtrar valores en función de una condición y transformarlos o descartarlos en el proceso. Ejemplo de transformación de valores: DABD Material de Estudio – U3 Pág. 15 import { of } from 'rxjs'; import { map } from 'rxjs/operators'; const numerosObservable = of(1, 2, 3, 4, 5); const cuadradosObservable = numerosObservable.pipe( map(numero => numero * numero) ); cuadradosObservable.subscribe(valor => { console.log(valor); // Esto imprimirá 1, 4, 9, 16, 25 }); En este ejemplo, el operador map se utiliza para elevar al cuadrado cada número emitido por el observable numerosObservable. Como resultado, el observable cuadradosObservable emite los valores 1, 4, 9, 16 y 25, que son los cuadrados de los números originales. Operador filter Se utiliza para filtrar los valores emitidos por un observable en función de una condición específica. Es útil cuando deseas obtener solo los elementos del flujo de datos que cumplen con ciertos criterios y deseas descartar los elementos que no cumplen con esa condición. El operador filter devuelve un nuevo observable que emite solo los valores que pasan la prueba de la condición especificada. Ejemplo para la aplicación de un filtro: import { of } from 'rxjs'; import { filter } from 'rxjs/operators'; const numerosObservable = of([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); const paresObservable = numerosObservable.pipe( filter(numero => numero % 2 === 0) ); paresObservable.subscribe(numeroPar => { console.log(numeroPar); // Esto imprimirá 2, 4, 6, 8, 10 }); Aquí el operador filter se utiliza para crear un nuevo observable llamado paresObservable. Este nuevo observable solo emitirá los números pares del observable original numerosObservable. La función de filtro numero => numero % 2 === 0 verifica si un número es par o no, y solo permite que los números pares pasen a través del observable resultante. DABD Material de Estudio – U3 Pág. 16 Operador switchMap Se utiliza para manejar y transformar observables en función de los eventos emitidos por otro observable. Su principal función es realizar una conmutación (switch) entre observables internos cuando se produce un nuevo evento en el observable de origen. es especialmente útil cuando estás trabajando con observables que representan eventos asincrónicos, como las solicitudes HTTP o eventos de usuario, y necesitas manejar y cancelar observables anteriores si un nuevo evento ocurre antes de que el observable anterior se complete. Ejemplo: import { fromEvent, interval } from 'rxjs'; import { switchMap } from 'rxjs/operators'; // Creamos un observable que emite eventos de clic del mouse const clickObservable = fromEvent(document, 'click'); // Cuando se hace clic en el documento, generamos un nuevo observable // que emite números cada segundo const resultadoObservable = clickObservable.pipe( switchMap(() => { return interval(1000); }) ); // Suscribimos un observador para observar los números emitidos después de cada clic resultadoObservable.subscribe(numero => { console.log(numero); }); En este ejemplo: Creamos un observable llamado clickObservable que emite eventos de clic del mouse en el documento. Usamos switchMap para "conmutar" a un nuevo observable cuando se produce un evento de clic. En este caso, generamos un observable que emite números cada segundo utilizando interval(1000). Cuando ocurre un clic en el documento, el observable resultante (resultadoObservable) comienza a emitir números cada segundo. Si se produce otro clic antes de que el observable interno complete su emisión de números, switchMap cancela el observable anterior y conmuta al nuevo observable interno generado por el segundo clic. DABD Material de Estudio – U3 Pág. 17 En resumen, switchMap es útil para gestionar observables en situaciones en las que deseas cambiar de un observable interno a otro en respuesta a eventos asincrónicos y, al mismo tiempo, garantizar que solo se maneje el observable más reciente y se cancele cualquier observación anterior. Esto es particularmente útil en aplicaciones que requieren interacciones de usuario y manejo de solicitudes asincrónicas, como aplicaciones web y móviles. Un ejemplo común de cómo usar switchMap con llamadas HTTP en RxJS es cuando deseas manejar solicitudes HTTP asincrónicas en respuesta a algún evento, como un clic de usuario, y deseas cancelar solicitudes anteriores si se produce un nuevo evento antes de que se complete la solicitud anterior Supongamos que tienes un botón en tu componente Angular y quieres realizar una solicitud HTTP a una API cuando el usuario hace clic en ese botón. Si el usuario hace varios clics rápidos, deseas cancelar cualquier solicitud anterior y solo manejar la solicitud más reciente. import { Component } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { switchMap } from 'rxjs/operators'; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) export class PruebaComponent { resultado: string | null = null; constructor(private http: HttpClient) { } realizarSolicitud() { // Creamos un observable de clics en el botón const botonObservable = new Observable(() => { return this.http.get('https://ejemplo.com/api/datos'); // Reemplaza la URL con tu endpoint real }); // Usamos switchMap para manejar las solicitudes HTTP y //cancelar las anteriores si se produce un nuevo clic botonObservable.pipe( switchMap(() => this.http.get('https://ejemplo.com/api/datos')) // Reemplaza la URL con tu endpoint real ).subscribe( (data: any) => { this.resultado = data; // Actualiza el resultado en el componente con los datos recibidos }, (error) => { console.error('Error al realizar la solicitud:', error); } ); } } DABD Material de Estudio – U3 Pág. 18 En este ejemplo: Creamos un observable botonObservable que representa los clics en el botón. Utilizamos switchMap para manejar las solicitudes HTTP. Cuando se produce un clic, se realiza una solicitud HTTP utilizando this.http.get(). Si se produce un nuevo clic antes de que se complete la solicitud anterior, switchMap cancelará la solicitud anterior y manejará la nueva solicitud. Actualizamos el resultado en el componente cuando se recibe una respuesta exitosa. Operador mergeMap Se utiliza para fusionar (merge) múltiples observables internos en un solo observable externo. Este operador es útil cuando deseas manejar observables internos y combinar sus resultados en un flujo de datos unificado. A menudo se utiliza para manejar observables generados por operaciones asincrónicas, como solicitudes HTTP o eventos de usuario, y combinar los resultados de estas operaciones en un solo flujo de datos observable. Dentro de mergeMap, cada valor emitido por la observable fuente genera un nuevo observable interno. A medida que los observables internos emiten valores, estos se fusionan en el observable externo sin ningún orden específico. Esto significa que si varios observables internos emiten valores al mismo tiempo, los valores se combinan en el observable externo en función de cuál llega primero. Ejemplo de cómo usar mergeMap para manejar solicitudes HTTP: import { of } from 'rxjs'; import { mergeMap } from 'rxjs/operators'; const userIds = [1, 2, 3, 4, 5]; // Creamos un observable a partir de un arreglo de IDs de usuario const userIdsObservable = of(..userIds); // Usamos mergeMap para realizar solicitudes HTTP para cada ID de usuario userIdsObservable.pipe( mergeMap((userId) => { const url = `https://jsonplaceholder.typicode.com/users/${userId}`; return this.httpClient.get(url);; // Se supone que httpClient proviene de una inyección de dicho // servicio en el constructor de la clase en la que se está trabajando }).subscribe(user => { console.log(user); }, error => { console.error('Error al realizar la solicitud HTTP:', error); }); ); DABD Material de Estudio – U3 Pág. 19 En este ejemplo: Creamos un observable llamado userIdsObservable a partir de un arreglo de IDs de usuario. Usamos mergeMap para realizar una solicitud HTTP para cada ID de usuario en el arreglo. Esto significa que se generarán múltiples observables internos, uno por cada ID de usuario. Los resultados de las solicitudes HTTP se fusionan en el observable externo, y cada objeto de usuario obtenido se imprime en la consola a medida que llega. Operador combineLatest Se utiliza para combinar las emisiones más recientes de múltiples observables en un nuevo observable. Este operador es útil cuando deseas combinar los valores más recientes de varios observables y realizar una acción cuando cualquiera de los observables originales emite un valor. Toma como argumento una serie de observables y emite un nuevo valor cada vez que cualquiera de los observables originales emite un valor. El nuevo valor emitido es un arreglo que contiene los valores más recientes de todos los observables. Esto significa que el nuevo valor reflejará el estado más reciente de todos los observables combinados. Ejemplo: import { timer } from 'rxjs'; import { combineLatest } from 'rxjs/operators'; // Creamos dos observables que emiten valores con intervalos diferentes const obs1 = timer(0, 1000); const obs2 = timer(500, 500); // Usamos combineLatest para combinar los valores más recientes de ambos observables const observablesCombinados = combineLatest(obs1, obs2); // Suscribimos un observador para observar los valores combinados observablesCombinados.subscribe(([v1, v2]) => { console.log(`Valor 1: ${v1}, Valor 2: ${v2}`); }); DABD Material de Estudio – U3 Pág. 20 En este ejemplo: Creamos dos observables, obs1 y obs2, que emiten valores a intervalos diferentes. Utilizamos combineLatest para combinar estos dos observables. Suscribimos un observador al obserbablesCombinados resultante para observar los valores combinados. Cada vez que cualquiera de los observables originales emite un valor, el observador se actualiza con los valores más recientes de ambos observables. Ten en cuenta que los valores combinados se emiten en un arreglo, y cada elemento del arreglo corresponde al valor más reciente de un observable en el orden en el que se pasaron los observables a combineLatest. En este caso, [v1, v2] representa los valores más recientes de obs1 y obs2, respectivamente. Es útil cuando necesitas realizar acciones basadas en los valores más recientes de múltiples observables, como combinar datos de sensores en una aplicación de IoT o mantener actualizada la interfaz de usuario con datos de diferentes fuentes. DABD Material de Estudio – U3 Pág. 21 Routing El enrutamiento (Routing) se utiliza para gestionar la navegación dentro de una aplicación web. Permite a los usuarios navegar entre diferentes vistas o componentes en la aplicación sin necesidad de recargar la página completa. Se basa en la configuración de rutas que mapean URLs a componentes específicos. Angular al ser un framework brinda a los desarrolladores de mecanismos para el manejo de la navegación con una batería de caracteristicas que permiten gestionar el manejo de rutas en nuestra SPA sin la necesidad de una librería extra. Configuración y uso Para poder definir las rutas de un módulo determinado es necesario importar el enrutamiento de Angular. import { RouterModule, Routes } from '@angular/router'; const routes: Routes = [ // Aquí deberán ir definidas las rutas para dicho módulo ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppModule { } Luego, define tus rutas dentro del arreglo routes. Cada ruta es un objeto que mapea una URL a un componente específico: import { RouterModule, Routes } from '@angular/router'; import { HomeComponent } from './home.component'; import { AboutComponent } from './about.component'; import { ContactComponent } from './contact.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'about', component: AboutComponent }, { path: 'contact', component: ContactComponent }, // Otras rutas aquí ]; … continua el archivo Puedes definir una ruta vacía '' como ruta predeterminada que se cargará cuando la aplicación se inicie. DABD Material de Estudio – U3 Pág. 22 Crear puntos de navegación: En tu plantilla (por ejemplo, en el archivo app.component.html), puedes agregar enlaces que lleven a las diferentes rutas utilizando la directiva routerLink. Por ejemplo: Inicio Acerca de Contacto routerLinkActive se usa para aplicar una clase CSS cuando la ruta está activa. Mostrar contenido dinámico: En el lugar donde deseas mostrar el contenido del componente correspondiente a la ruta actual, puedes usar la directiva router-outlet. Por ejemplo: El componente asociado a la ruta actual se cargará y mostrará en este espacio. Navegación desde componentes TypeScript También puedes navegar programáticamente a través de rutas en los componentes. Para ello, es necesario agregar el servicio Router. Puedes importarlo y usarlo para navegar a una ruta específica: Teniendo la siguiente configuración de rutas para un componente de contactos: const routes: Routes = [ { path: contacto', component: ContactoComponent } ]; Es posible navegar a dicho componente de la siguiente manera; import { Router } from '@angular/router'; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) DABD Material de Estudio – U3 Pág. 23 export class PruebaComponent { constructor(private router: Router) {} // Luego, en una función por ejemplo: navegarAContacto() { this.router.navigate(['/contacto']); // Prestar atención al detalle de que la función navigate recibe un arreglo. } } Obtención valores por Ruta Para obtener los valores de la URL por medio de la ruta (route) actual usando el enrutamiento (routing) es necesario utilizar el servicio ActivatedRoute del paquete @angular/router. Aquí hay un ejemplo de cómo hacerlo: Configuración rutas: const routes: Routes = [ { path: detalle/:id', component: DetalleComponent } ]; Componente: import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) export class PruebaComponent implements OnInit { constructor(private activatedRoute: ActivatedRoute) {} ngOnInit() { this.route.params.subscribe(params => { // 'id' es el nombre del parámetro definido en la ruta this.id = params['id']; // Ahora, puedes usar this.id en tu componente para acceder al valor del parámetro 'id'. }); } } DABD Material de Estudio – U3 Pág. 24 Con esto, puedes obtener el valor de 'id' de la URL y utilizarlo en tu componente. Por ejemplo, si la URL es "/detalle/123", this.id contendrá el valor "123". Asegúrate de ajustar el nombre del parámetro (id en este caso) para que coincida con el nombre definido en tu ruta. Obtención valores por QueryString Para obtener valores de la cadena de consulta (query parameters), se puede utilizar el servicio ActivatedRoute del paquete @angular/router. Los valores de la cadena de consulta son los parámetros que se encuentran en la URL después del signo de interrogación (?). Aquí hay un ejemplo de cómo puedes obtener valores de la cadena de consulta en Angular: Supongamos que tienes una URL como esta: http://localhost:4200/productos?categoria=electronica&precio=500. Quieres obtener los valores de los parámetros categoria y precio de la cadena de consulta. import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; @Component({ selector: ’app-prueba’, templateUrl: ’./app-prueba.component.html’ }) export class PruebaComponent implements OnInit { constructor(private activatedRoute: ActivatedRoute) {} ngOnInit() { // Obtiene todos los parámetros de la cadena de consulta como un objeto. this.route.params.subscribe(params => { // params contiene los valores de la cadena de consulta como pares clave-valor. // Por ejemplo, params.categoria contendrá "electronica" y // params.precio contendrá "500". // Ahora puedes usar params para acceder a los valores de la cadena de consulta. const categoria = params['categoria']; const precio = params['precio']; // A continuación se pueden utilizar estos valores para lo que se desee, // incluso podrían ser guardados en una variable del componente // para usarla en otra función }); } } DABD Material de Estudio – U3 Pág. 25 Con esto, puedes obtener y utilizar los valores de la cadena de consulta en tu componente. En el ejemplo anterior, categoria contendrá "electronica" y precio contendrá "500" en función de la URL proporcionada. DABD Material de Estudio – U3 Pág. 26 Bibliografía https://angular.io/guide/observables https://angular.io/api/common/AsyncPipe https://angular.io/guide/router https://angular.io/guide/router-tutorial https://rxjs.dev/api/index/function/map https://rxjs.dev/api/index/function/filter https://rxjs.dev/api/index/function/mergeMap https://rxjs.dev/api/index/function/switchMap https://rxjs.dev/api/index/function/combineLatest Atribución-No Comercial-Sin Derivadas Se permite descargar esta obra y compartirla, siempre y cuando no sea modificado y/o alterado su contenido, ni se comercialice. Universidad Tecnológica Nacional Facultad Regional Córdoba (S/D). Material para la Tecnicatura Universitaria en Programación, modalidad virtual, Córdoba, Argentina. DABD Material de Estudio – U3 Pág. 27

Use Quizgecko on...
Browser
Browser