Sebastian Gomez
En este post, vamos a 🔎 explorar cómo aumentar el número de operadores en un Observable añadiendo el operador map. 🌐
Recordemos del post anterior, donde implementamos el operador map en observables desde cero, de manera similar a como lo hace RX.js. Ahora, vamos a incrementar la cantidad de operadores que podemos usar en un Observable. 📈
Primero, echemos un vistazo a la definición más pura de un Observable con una función generadora de observables a partir de eventos:
// Define una clase llamada Observable
class Observable {
// El constructor de la clase recibe una función de suscripción
constructor(subscribe) {
// Almacena la función de suscripción en una propiedad privada
this._subscribe = subscribe;
}
// Método para suscribir un observador al observable
subscribe(observer) {
// Ejecuta la función de suscripción con el observador proporcionado
return this._subscribe(observer);
}
// Método estático que crea un observable a partir de un evento del DOM
static fromEvent(domElement, eventName) {
// Retorna una nueva instancia de Observable
return new Observable(function subscribe(observer) {
// Define un manejador de eventos que invoca el método next del observador con el evento
const handler = (ev) => {
observer.next(ev);
};
// Añade el manejador de eventos al elemento del DOM para el nombre del evento dado
domElement.addEventListener(eventName, handler);
// Retorna un objeto con un método para cancelar la suscripción al evento
return {
unsubscribe() {
// Elimina el manejador de eventos del elemento del DOM
domElement.removeEventListener(eventName, handler);
},
};
});
}
}
Con esto, puedes crear Observables que devuelven información del evento de la siguiente manera:
// Obtiene una referencia al botón con ID "button" del documento HTML
const button = document.getElementById("button");
// Crea un observable llamado "clicks" utilizando el método estático "fromEvent" de la clase Observable,
// suscribiendo al botón al evento "click"
const clicks = Observable.fromEvent(button, "click");
// Suscribe un objeto observador al observable "clicks" y almacena la suscripción en "clicksSubscription"
const clicksSubscription = clicks.subscribe({
// Define el método "next" del objeto observador para manejar eventos de clic en el botón
next(e) {
// Registra en la consola un mensaje indicando que se hizo clic en el botón y muestra el objeto del evento "e"
console.log("Click in the button", e); // "e" contiene toda la información del evento
}
});
// Cancela la suscripción a eventos de clic en el botón utilizando el método "unsubscribe" del objeto de suscripción
clicksSubscription.unsubscribe(); // Así te puedes des-suscribir
Pero, a veces necesitamos realizar más operaciones sobre la cadena de datos. Por ejemplo, si queremos obtener sólo algunos datos del evento, como la posición del Mouse 🖱️, o si sólo queremos escuchar los clicks que se hagan en la parte izquierda del botón. Para ello, vamos a implementar la función filter sobre Observables. 🎯
📖 Ejemplo de filter en ArraysVeamos cómo funciona filter en Arrays de JavaScript antes de implementarlo en Observables:
[1, 2, 3, 4].filter((x) => x > 3);
// retorna [4]
filter, al igual que map, recibe una función como parámetro. Esta función es de validación y retorna true o false. El operador filter devuelve el elemento para el cual la función de validación es true.
🎩 Implementando filter en Observables// Define un método "filter" que toma una función de validación como argumento
filter(validationFunction) {
// Almacena una referencia al objeto actual en la variable "self"
const self = this;
// Retorna un nuevo observable
return new Observable(function subscribe(observer) {
// Suscribe un objeto observador al observable actual ("self") y almacena la suscripción en "subscription"
const subscription = self.subscribe({
// Define el método "next" del objeto observador para manejar los valores emitidos por el observable
next(v) {
// Si la función de validación retorna verdadero para el valor "v", pasa el valor al método "next" del observador
if(validationFunction(v)) {
observer.next(v);
}
},
// Define el método "error" del objeto observador para manejar errores emitidos por el observable
error (e) {
// Pasa el error "e" al método "error" del observador
observer.error(e);
},
// Define el método "complete" del objeto observador para manejar la finalización del observable
complete () {
// Llama al método "complete" del observador
observer.complete();
}
});
// Retorna la suscripción
return subscription;
});
}
Ahora veamos cómo usar el operador filter en Observables para filtrar los clicks que se hacen en la parte izquierda del botón:
// Obtiene una referencia al botón con ID "button" del documento HTML
const button = document.getElementById("button");
// Crea un observable llamado "clicks" utilizando el método estático "fromEvent" de la clase Observable,
// suscribiendo al botón al evento "click"
const clicks = Observable.fromEvent(button, "click");
// Filtra y transforma los eventos de clic antes de suscribir un objeto observador
const clicksSubscription = clicks
// Aplica el método "filter" para permitir solo eventos en los que la posición X del mouse sea menor a 40
.filter((ev) => ev.offsetX < 40)
// Aplica el método "map" para transformar el evento en su posición X del mouse (offsetX)
.map((ev) => ev.offsetX)
// Suscribe un objeto observador a los eventos filtrados y transformados
.subscribe({
// Define el método "next" del objeto observador para manejar eventos de clic en el botón
next(offSetX) {
// Registra en la consola un mensaje indicando la posición X del mouse en el momento del clic
console.log("La posición del mouse respecto a X " + offSetX); // Solo imprime si haces click a la izquierda de "Me"
},
});
Aquí tienes el ejemplo completo con la implementación de `filter` y `map`:
🔗 [https://codepen.io/seagomezar/pen/WdVzxB](https://codepen.io/seagomezar/pen/WdVzxB)
1. Hemos aprendido a implementar el operador `filter` en Observables para filtrar y procesar los eventos que cumplan con ciertos criterios. 🎉 2. Los operadores en Observables, como `filter` y `map`, permiten manipular y realizar operaciones sobre la cadena de datos de manera más eficiente. 🛠️ 3. Los operadores sobre Observables siguen una lógica similar y, en su mayoría, deben retornar un nuevo Observable. Las operaciones o filtros sobre los valores se realizan en la función `next`. 🔄
1. Crea un Observable que filtre y muestre solo los clicks realizados con el botón derecho del mouse. 2. Implementa un Observable que filtre y muestre solo los eventos de teclado con teclas de flechas (arriba, abajo, izquierda y derecha). 3. Combina los operadores `filter` y `map` para crear un Observable que filtre eventos de teclado y transforme la salida en un objeto que contenga información relevante sobre la tecla presionada (por ejemplo, el nombre de la tecla y si fue presionada con alguna tecla modificadora como Shift, Ctrl, etc.).
1. Aprendimos a implementar y utilizar el operador `filter` en Observables. 2. Entendimos cómo funcionan los operadores en Observables, como `filter` y `map`, para manipular eventos. 3. Vimos ejemplos de cómo aplicar `filter` y `map` en casos de uso reales, como filtrar clicks y eventos de teclado
💡 Ideas adicionales para aplicar lo aprendidoEstas ideas adicionales te ayudarán a aplicar y consolidar lo aprendido en el post sobre la implementación de filter en Observables. No olvides que puedes combinar diferentes operadores para lograr resultados más complejos y adaptados a tus necesidades. ¡Buena suerte en tus proyectos y sigue explorando las posibilidades que ofrecen los Observables! 🚀
Creador de contenido principalmente acerca de tecnología.