Saltar al contenido principal

Eventos y EventEmitter

Node.js utiliza un modelo basado en eventos para gestionar operaciones asíncronas. Un evento representa una acción o suceso que ocurre en el sistema, como la llegada de datos, la finalización de una tarea o la interacción del usuario. Este enfoque permite que el código responda a sucesos de manera eficiente, sin bloquear el event loop.

EventEmitter

La clase EventEmitter es el núcleo del sistema de eventos en Node.js. Permite crear objetos que pueden emitir eventos y escuchar su ocurrencia mediante listeners. La clase EventEmitter se encuentra en el módulo events, que es nativo de Node.js.

Ejemplo básico de EventEmitter:

import EventEmitter from 'events';

const emisor = new EventEmitter();

// Registrar un listener para el evento 'mensaje'
emisor.on('mensaje', (texto) => {
console.log(`Se recibió el mensaje: ${texto}`);
});

// Emitir el evento 'mensaje'
emisor.emit('mensaje', 'Hola mundo!');

En este ejemplo, se crea un emisor de eventos, se registra un listener para el evento 'mensaje' y luego se dispara el evento con emit. Cuando se emite, se ejecuta automáticamente la función asociada.

Métodos importantes

  • on(evento, listener): Registra un listener que se ejecutará cada vez que se emita el evento.
  • once(evento, listener): Registra un listener que solo se ejecutará la primera vez que ocurra el evento.
  • emit(evento, ...args): Emite un evento, ejecutando todos los listeners asociados.
  • removeListener(evento, listener): Elimina un listener específico.
  • removeAllListeners(evento): Elimina todos los listeners de un evento.

Ejemplo con once y removeListener:

function saludo(nombre) {
console.log(`Hola, ${nombre}`);
}

emisor.once('saludo', saludo);
emisor.emit('saludo', 'Ana'); // Se ejecuta
emisor.emit('saludo', 'Carlos'); // No se ejecuta, porque fue 'once'

emisor.on('despedida', saludo);
emisor.removeListener('despedida', saludo);
emisor.emit('despedida', 'Ana'); // No se ejecuta

Uso práctico

El patrón de eventos es muy común en Node.js, especialmente en módulos que manejan operaciones asíncronas o flujos de datos, como:

  • fs para leer archivos mediante streams (fs.createReadStream).
  • http para gestionar peticiones y respuestas en servidores.
  • Librerías como Socket.IO o EventEmitter personalizados para aplicaciones en tiempo real.

Buenas prácticas

Al trabajar con eventos y EventEmitter, es recomendable:

  • Evitar listeners anónimos si luego se necesita eliminarlos.
  • Registrar y limpiar listeners de manera controlada para prevenir fugas de memoria.
  • Usar once cuando solo se necesita ejecutar la función una vez.
  • Mantener la lógica de los listeners simple y delegar tareas complejas a funciones externas.