Is event loop part of V8?

Eventos en NodeJS: Guía Completa para Aplicaciones Escalables

hace 3 años

★★★★★Valoración: 3.97 (1075 votos)

Node.js se basa en una arquitectura impulsada por eventos, un paradigma fundamental para construir aplicaciones altamente escalables y reactivas. Comprender la naturaleza basada en eventos de Node.js y cómo trabajar con ellos es esencial para desarrollar aplicaciones eficientes que puedan manejar un gran número de conexiones concurrentes sin sacrificar el rendimiento. En este artículo, exploraremos en profundidad el sistema de eventos de Node.js, desde los conceptos básicos hasta las técnicas más avanzadas, proporcionándote el conocimiento y las herramientas necesarias para dominar este aspecto crucial del desarrollo en Node.js.

Does NodeJS have an event loop?
Node. js is an open-source JavaScript runtime environment that allows you to run JavaScript outside the browser. Although Node. js is single-threaded, it has an event loop that makes it multi-threaded.
Índice de Contenido

¿Qué son los Eventos en Node.js?

En Node.js, un evento representa una acción o suceso detectable y manejable por tu programa. La arquitectura basada en eventos permite la programación asíncrona, lo que significa que tu aplicación puede realizar operaciones sin bloqueo. En otras palabras, mientras espera que se complete una operación (como leer un archivo o realizar una solicitud de red), la aplicación puede seguir procesando otras tareas. Esta capacidad de realizar operaciones de entrada/salida (E/S) de forma no bloqueante es una de las claves de la eficiencia y escalabilidad de Node.js.

La Clase EventEmitter

El núcleo del sistema de eventos de Node.js es la clase EventEmitter. Esta clase, incluida en el módulo `events` incorporado, permite que los objetos emitan eventos con nombre que pueden ser escuchados por otras partes de tu aplicación. Es la base para implementar el patrón observador en Node.js, facilitando la comunicación entre diferentes componentes de una aplicación de manera desacoplada y eficiente.

Características Clave de EventEmitter:

  • Registro de Eventos: Puedes registrar listeners (oyentes) para eventos específicos utilizando el método `on()`. Estos listeners son funciones que se ejecutarán cuando se emita el evento correspondiente.
  • Emisión de Eventos: Utiliza el método `emit()` para desencadenar un evento y llamar a todos los listeners registrados para ese evento. Puedes pasar argumentos al método `emit()` que se enviarán a los listeners.
  • Ejecución Asíncrona: Los listeners pueden ejecutarse de forma asíncrona, permitiendo que otras operaciones continúen mientras se espera que se procesen los eventos. Esto es fundamental para mantener la capacidad de respuesta de la aplicación.

Sintaxis Básica:

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); 

Para empezar a trabajar con eventos, primero debes importar el módulo `events` y crear una instancia de la clase `EventEmitter`. Esta instancia será tu emisor de eventos, y sobre ella registrarás listeners y emitirás eventos.

Trabajando con Eventos en Node.js Paso a Paso

Paso 1: Importar el Módulo de Events

El primer paso es importar el módulo `events` en tu archivo JavaScript y crear una instancia de `EventEmitter`:

const EventEmitter = require('events'); const myEmitter = new EventEmitter(); 

Paso 2: Registrar Event Listeners

Utiliza el método `on()` para registrar listeners para eventos específicos. El primer argumento es el nombre del evento (una cadena), y el segundo argumento es la función de callback que se ejecutará cuando se emita el evento.

myEmitter.on('eventoPersonalizado', () => { console.log('¡Se ha producido un evento personalizado!'); }); 

En este ejemplo, hemos registrado un listener para el evento llamado `eventoPersonalizado`. Cuando se emita este evento, la función de callback se ejecutará y mostrará el mensaje en la consola.

Paso 3: Emitir Eventos

Para desencadenar un evento, utiliza el método `emit()` con el nombre del evento como primer argumento. Puedes pasar argumentos adicionales al método `emit()` que se enviarán a los listeners.

myEmitter.emit('eventoPersonalizado'); // Output: ¡Se ha producido un evento personalizado! 

Al ejecutar `myEmitter.emit('eventoPersonalizado')`, se notifica a todos los listeners registrados para el evento `eventoPersonalizado`, y sus funciones de callback se ejecutan en el orden en que fueron registrados.

Métodos para Escuchar Eventos

Node.js proporciona varios métodos para registrar listeners de eventos, ofreciendo flexibilidad y control sobre cómo se manejan los eventos.

How to use events in NodeJS?
WORKING WITH EVENTS IN NODE.JS , Step 1: Importing the Events Module. To start using events in your application, you need to import the events module and create an instance of the EventEmitter class. ... , Step 2: Registering Event Listeners. ... , Step 3: Emitting Events.

`eventEmitter.addListener(evento, listener)` y `eventEmitter.on(evento, listener)`

Estos dos métodos son esencialmente alias y funcionan de la misma manera. Registran una función de listener para el evento especificado. El listener se añade al final de la lista de listeners para ese evento y se invocará cada vez que se emita el evento.

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); const listener1 = (mensaje) => { console.log('Listener 1:', mensaje); }; const listener2 = (mensaje) => { console.log('Listener 2:', mensaje); }; eventEmitter.on('miEvento', listener1); eventEmitter.addListener('miEvento', listener2); eventEmitter.emit('miEvento', '¡Evento emitido!'); // Output: // Listener 1: ¡Evento emitido! // Listener 2: ¡Evento emitido! 

`eventEmitter.once(evento, listener)`

El método `once()` registra un listener que se ejecutará solo la primera vez que se emita el evento. Después de la primera ejecución, el listener se elimina automáticamente de la lista de listeners.

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); eventEmitter.once('eventoUnico', () => { console.log('Este listener se ejecuta solo una vez.'); }); eventEmitter.emit('eventoUnico'); eventEmitter.emit('eventoUnico'); // No tendrá efecto // Output: Este listener se ejecuta solo una vez. 

Eliminando Listeners de Eventos

En ocasiones, es necesario eliminar listeners de eventos registrados previamente. Node.js proporciona métodos para eliminar listeners específicos o todos los listeners de un evento.

`eventEmitter.removeListener(evento, listener)`

Este método elimina un listener específico del array de listeners asociado al evento. Toma dos argumentos: el nombre del evento y la función listener que se va a eliminar. Es importante tener en cuenta que `removeListener()` solo eliminará la primera instancia del listener si se ha registrado el mismo listener varias veces.

`eventEmitter.removeAllListeners([evento])`

Este método elimina todos los listeners registrados para un evento específico. Si no se proporciona el argumento `evento`, elimina todos los listeners de todos los eventos registrados en el `EventEmitter`.

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); const fun1 = (msg) => { console.log('Mensaje de fun1:', msg); }; const fun2 = (msg) => { console.log('Mensaje de fun2:', msg); }; eventEmitter.on('miEvento', fun1); eventEmitter.on('miEvento', fun1); // Registrado dos veces eventEmitter.on('miEvento', fun2); eventEmitter.removeListener('miEvento', fun1); // Elimina una instancia de fun1 eventEmitter.emit('miEvento', 'Evento emitido'); // Output: // Mensaje de fun1: Evento emitido // Mensaje de fun2: Evento emitido eventEmitter.removeAllListeners('miEvento'); // Elimina todos los listeners de 'miEvento' eventEmitter.emit('miEvento', 'Evento emitido de nuevo'); // No tendrá efecto 

Nota Importante: Eliminar listeners puede cambiar el orden de ejecución de los listeners restantes, por lo que debe usarse con precaución.

Otros Métodos Útiles de EventEmitter

Además de los métodos básicos para registrar y emitir eventos, la clase `EventEmitter` ofrece otros métodos que proporcionan información y control adicionales sobre los listeners de eventos.

`eventEmitter.listeners(evento)`

Este método devuelve un array con todos los listeners registrados para el evento especificado. Es útil para inspeccionar los listeners asociados a un evento en tiempo de ejecución.

`eventEmitter.listenerCount(evento)`

Devuelve el número de listeners registrados para el evento especificado. Es una forma rápida de obtener la cantidad de listeners sin obtener el array completo.

What is the handler function in NodeJS?
The handler function in Node. js accepts two main parameters: event and context. Event: It is the parameter that encapsulates all the event data that caused the function to be executed.

`eventEmitter.prependOnceListener(evento, listener)`

Similar a `once()`, pero añade el listener al principio del array de listeners para el evento especificado. Esto asegura que este listener se ejecute primero cuando se emita el evento, y solo se ejecutará una vez.

`eventEmitter.prependListener(evento, listener)`

Similar a `on()`, pero añade el listener al principio del array de listeners para el evento especificado. Esto asegura que este listener se ejecute primero cuando se emita el evento.

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); const fun1 = (msg) => { console.log('Mensaje de fun1:', msg); }; const fun2 = (msg) => { console.log('Mensaje de fun2:', msg); }; eventEmitter.addListener('miEvento', fun1); // Añade al final eventEmitter.prependListener('miEvento', fun2); // Añade al principio console.log(eventEmitter.listeners('miEvento')); console.log(eventEmitter.listenerCount('miEvento')); eventEmitter.emit('miEvento', 'Evento emitido'); // Output: // [ [Function: fun2], [Function: fun1] ] // 2 // Mensaje de fun2: Evento emitido // Mensaje de fun1: Evento emitido 

Eventos Especiales de EventEmitter

Todas las instancias de `EventEmitter` emiten dos eventos especiales: `'newListener'` cuando se añaden nuevos listeners y `'removeListener'` cuando se eliminan listeners existentes. Además, el evento `'error'` se utiliza para manejar errores dentro del `EventEmitter`.

Evento: `'newListener'`

El evento `'newListener'` se emite antes de que un nuevo listener se añada al array interno de listeners. Los listeners registrados para `'newListener'` reciben el nombre del evento y una referencia al listener que se está añadiendo.

Evento: `'removeListener'`

El evento `'removeListener'` se emite después de que un listener ha sido eliminado.

Evento: `'error'`

Cuando ocurre un error dentro de una instancia de `EventEmitter`, la acción típica es emitir un evento `'error'`. Si no hay al menos un listener registrado para el evento `'error'`, y se emite un evento `'error'`, el error se lanza como una excepción no controlada, se imprime un stack trace y el proceso de Node.js se cierra. Es crucial manejar el evento `'error'` para evitar cierres inesperados de la aplicación.

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); eventEmitter.on('error', (err) => { console.error('¡Vaya! Ocurrió un error:', err.message); }); eventEmitter.on('newListener', (event, listener) => { console.log(`Listener añadido al evento: ${event}`); }); eventEmitter.on('removeListener', (event, listener) => { console.log(`Listener eliminado del evento: ${event}`); }); const listener1 = (msg) => { console.log('Mensaje de listener1:', msg); }; const listener2 = (msg) => { console.log('Mensaje de listener2:', msg); }; eventEmitter.on('miEvento', listener1); eventEmitter.on('miEvento', listener2); eventEmitter.off('miEvento', listener1); eventEmitter.emit('miEvento', 'Evento emitido'); eventEmitter.emit('error', new Error('¡Algo salió mal!')); // Output (aproximado, el orden de los eventos 'newListener' puede variar): // Listener añadido al evento: removeListener // Listener añadido al evento: miEvento // Listener añadido al evento: miEvento // Listener eliminado del evento: miEvento // Mensaje de listener2: Evento emitido // ¡Vaya! Ocurrió un error: ¡Algo salió mal! 

Eventos Asíncronos

Por defecto, `EventEmitter` llama a todos los listeners de forma síncrona, en el orden en que fueron registrados. Sin embargo, puedes realizar llamadas asíncronas a listeners utilizando `setImmediate()` o `process.nextTick()`. Esto es útil para evitar bloquear el hilo principal de ejecución, especialmente si los listeners realizan operaciones costosas o de larga duración.

const EventEmitter = require('events'); const eventEmitter = new EventEmitter(); eventEmitter.on('miEvento', (msg) => { setImmediate(() => { console.log('Mensaje de listener asíncrono:', msg); }); }); const listenerSincrono = (msg) => { console.log('Mensaje de listener síncrono:', msg); }; eventEmitter.on('miEvento', listenerSincrono); eventEmitter.emit('miEvento', 'Evento emitido'); // Output (el orden puede variar ligeramente): // Mensaje de listener síncrono: Evento emitido // Mensaje de listener asíncrono: Evento emitido 

En este ejemplo, el listener asíncrono se ejecuta después del listener síncrono, incluso si ambos están registrados para el mismo evento. `setImmediate()` permite que el listener asíncrono se ejecute en la siguiente iteración del bucle de eventos, después de que el hilo principal haya terminado de procesar las tareas síncronas.

Preguntas Frecuentes (FAQs) sobre Eventos en Node.js

  1. ¿Qué es un evento en Node.js?

    Un evento en Node.js es una acción o suceso que el programa puede detectar y manejar. Permite la programación asíncrona y la creación de aplicaciones no bloqueantes.

    What is HTTP request in NodeJS?
    The HTTP POST method is employed by the World Wide Web to send data to a server. This request method is characterized by the inclusion of data in the request body, and the type of this body is specified by the Content-Type header. Express.js, a web application framework for Node, facilitates the cre.
  2. ¿Qué es la clase EventEmitter?

    La clase EventEmitter es el núcleo del sistema de eventos en Node.js. Permite a los objetos emitir eventos con nombre que pueden ser escuchados por otros componentes de la aplicación.

  3. ¿Cómo se registra un listener para un evento?

    Se utiliza el método `on()` o `addListener()` para registrar un listener. El primer argumento es el nombre del evento, y el segundo es la función de callback a ejecutar.

  4. ¿Cómo se emite un evento?

    Se utiliza el método `emit()` con el nombre del evento como primer argumento. Se pueden pasar argumentos adicionales a los listeners.

  5. ¿Cuál es la diferencia entre `on()` y `once()`?

    `on()` registra un listener que se ejecuta cada vez que se emite el evento. `once()` registra un listener que se ejecuta solo la primera vez que se emite el evento.

  6. ¿Cómo se eliminan los listeners de eventos?

    Se utiliza `removeListener(evento, listener)` para eliminar un listener específico y `removeAllListeners([evento])` para eliminar todos los listeners de un evento o todos los eventos.

  7. ¿Qué son los eventos especiales `'newListener'`, `'removeListener'` y `'error'`?

    Son eventos especiales emitidos por `EventEmitter` para notificar sobre la adición de listeners (`'newListener'`), la eliminación de listeners (`'removeListener'`) y errores dentro del emisor (`'error'`). Es crucial manejar el evento `'error'` para evitar cierres inesperados de la aplicación.

  8. ¿Cómo se manejan los eventos asíncronos?

    Se pueden utilizar `setImmediate()` o `process.nextTick()` dentro de los listeners para ejecutar el código de forma asíncrona y evitar bloquear el hilo principal.

Conclusión

El sistema de eventos de Node.js, basado en la clase EventEmitter, es un pilar fundamental para construir aplicaciones escalables y reactivas. Comprender cómo registrar listeners, emitir eventos, y manejar los diferentes métodos y eventos especiales te permitirá aprovechar al máximo la arquitectura basada en eventos de Node.js. Dominar este concepto es esencial para cualquier desarrollador de Node.js que busque crear aplicaciones eficientes, robustas y capaces de manejar la concurrencia de manera efectiva.

Subir