Concatenando observables en RXJS 馃У

Publicado el 02.07.2023 a las 22:56

Concatenando observables en RXJS 馃У

  1. 驴Por qu茅 necesito saber concatenar observables?

  2. Concatenando observables

    • Operador concatAll

    • Operador concatMap

    • Operador switchMap

Logo de fjmduran

Concatenando observables en RXJS 馃У

Programando, en ocasiones, se hace obligatorio esperar una respuesta para poder continuar con el flujo de la aplicaci贸n.


En aplicaciones de backend podemos generar varios hilos para evitar bloquear la aplicaci贸n mientras se espera una respuesta, ya sea un c谩lculo o una petici贸n a otra fuente de datos.


En frontend, para no bloquear la aplicaci贸n usamos programaci贸n reactiva.


Antes us谩bamos los callbacks.

No quiero recordar cuando no exist铆an las promesas y todo eran callbacks, la que se liaba cuando quer铆as concatenar varios callback, lo que conocemos como callback hell 馃懞


A partir del ECMAScript 6 se introdujeron las promesas y se nos facilit贸 el c贸digo as铆ncrono.


Con las nuevas palabras claves de async y await que a帽adieron en ECMAScript 2017 se nos proporcion贸 una manera a煤n m谩s f谩cil y legible de hacer programaci贸n as铆ncrona con las promesas.


驴Pero qu茅 ocurre cuando trabajamos con observables?

驴Por qu茅 necesito saber concatenar observables?

Cuando trabajamos con Angular y hacemos peticiones HTTP con su cliente trabajaremos con observables, por eso es necesario saber concatenarlos si no queremos ir anidando observables al estilo del callback hell.


Los observables son un patr贸n de dise帽o utilizado en programaci贸n reactiva.


Representa una fuente de datos o eventos asincr贸nicos y permite a los observadores suscribirse a ella para recibir notificaciones cuando ocurran cambios en dichos datos.


Te cuento c贸mo podemos concatenar varios observables usando operadores de orden superior de RXJS.

Concatenando observables

Te voy a explicar 3 formas de concatenar observables, pero antes puede que te preguntes por qu茅 te podr铆a hacer falta aprender a concatenar observables.


Imagina que necesitas obtener una factura de un cliente haciendo una consulta a una API, pero s贸lo tienes el n煤mero de factura.


La API s贸lo acepta consultas por Id, pues lo que tendr铆amos que hacer ser铆a:

  1. Obtener el Id de la factura pas谩ndole a la API el c贸digo de cliente y n煤mero de factura
  2. Una vez que obtengas la respuesta de la primera consulta, con el id de la factura, hacer la petici贸n con ese n煤mero de id.

Si te fijas, es obligatorio esperar que se resuelva la primera petici贸n para que el proceso se ejecute satisfactoriamente.


Vamos a ver c贸mo podemos hacerlo con observables.


Para los ejemplos voy a utilizar la API que nos proporciona de forma gratuita reqres.in

Operador concatAll

El operador concatAll se utiliza para fusionar un observable de observables.


Toma un observable que emite observables como emisiones y los concatena en un solo observable.


Es decir, se suscribe secuencialmente a cada observable interno y emite sus valores en orden.


Solo pasa al siguiente observable interno cuando el anterior ha terminado.

this.http
    .get<RawData>('https://reqres.in/api/users?page=2')
    .pipe(
        map((response) => response.data[0].id),
        map((id: number) =>
        this.http.get<SingleUser>(`https://reqres.in/api/users/${id}`)
        ),
        concatAll()
    );
      

Para tipar las respuestas de los observables he usado las siguiente interfaces:

export interface RawData {
    page: number;
    per_page: number;
    total: number;
    total_pages: number;
    data: User[];
    support: Support;
    }
              
export interface User {
    id: number;
    email: string;
    first_name: string;
    last_name: string;
    avatar: string;
    }

export interface Support {
    url: string;
    text: string;
    }
      
export interface SingleUser {
    data: User;
    support: Support;
    }
        

Operador concatMap

El operador concatMap se utiliza para mapear los resultados de varios observables en un solo observable de salida.


Mantiene el orden relativo de las emisiones y espera a que cada observable interno se complete antes de pasar al siguiente.

this.http
    .get<RawData>('https://reqres.in/api/users?page=2')
    .pipe(
        concatMap((response) => response.data[0].id),
        concatMap((id: number) =>
        this.http.get<SingleUser>(`https://reqres.in/api/users/${id}`)
        ).subscribe((data)=>{
            //Aqu铆 lo que quieras hacer con la respuesta del 煤ltimo observable
        })
    );
                  

Operador switchMap

El operador switchMap se utiliza para mapear cada valor de un observable de entrada a un observable interno y, posteriormente, emitir los valores del observable interno.


Si se emiten nuevos valores en el observable de entrada antes de que el observable interno haya terminado, se cancela el observable interno actual y se cambia al nuevo observable.


Aqu铆 es donde radica la caracter铆stica principal del operador switchMap, en que se cancela el observable actual si se reciben nuevos datos.


Es muy utilizado con las cajas de b煤squedas.

Imagina la t铆pica caja de b煤squeda de un e-commerce, cuando el usuario escribe se hace la petici贸n a la API, pero si el usuario vuelve a escribir antes de recibir la respuesta de la API se cancelar谩 la primera petici贸n.

this.http
    .get<RawData>('https://reqres.in/api/users?page=2')
    .pipe(
        map((response) => response.data[1].id),
        switchMap((id: number) =>
        this.http.get<SingleUser>(`https://reqres.in/api/users/${id}`)
        )
    );
        

Hasta luego 馃枛