Eventos
[Estable: 2 - Estable]
Estable: 2 Estabilidad: 2 - Estable
Código Fuente: lib/events.js
Gran parte de la API principal de Node.js está construida alrededor de una arquitectura idiomática asíncrona impulsada por eventos en la que ciertos tipos de objetos (llamados "emisores") emiten eventos nombrados que hacen que se llamen objetos Function
("oyentes").
Por ejemplo: un objeto net.Server
emite un evento cada vez que un par se conecta a él; un fs.ReadStream
emite un evento cuando se abre el archivo; un stream emite un evento cada vez que hay datos disponibles para ser leídos.
Todos los objetos que emiten eventos son instancias de la clase EventEmitter
. Estos objetos exponen una función eventEmitter.on()
que permite adjuntar una o más funciones a eventos nombrados emitidos por el objeto. Por lo general, los nombres de los eventos son cadenas con formato camelCase, pero se puede usar cualquier clave de propiedad de JavaScript válida.
Cuando el objeto EventEmitter
emite un evento, todas las funciones adjuntas a ese evento específico se llaman síncronamente. Cualquier valor devuelto por los oyentes llamados es ignorado y descartado.
El siguiente ejemplo muestra una instancia simple de EventEmitter
con un solo oyente. El método eventEmitter.on()
se utiliza para registrar oyentes, mientras que el método eventEmitter.emit()
se utiliza para activar el evento.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('¡Ocurrió un evento!')
})
myEmitter.emit('event')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('¡Ocurrió un evento!')
})
myEmitter.emit('event')
Pasar argumentos y this
a los listeners
El método eventEmitter.emit()
permite pasar un conjunto arbitrario de argumentos a las funciones de listener. Ten en cuenta que cuando se llama a una función de listener ordinaria, la palabra clave estándar this
se establece intencionalmente para hacer referencia a la instancia de EventEmitter
a la que está adjunto el listener.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', function (a, b) {
console.log(a, b, this, this === myEmitter)
// Imprime:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
})
myEmitter.emit('event', 'a', 'b')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', function (a, b) {
console.log(a, b, this, this === myEmitter)
// Imprime:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
})
myEmitter.emit('event', 'a', 'b')
Es posible usar Funciones Flecha ES6 como listeners, sin embargo, al hacerlo, la palabra clave this
ya no hará referencia a la instancia de EventEmitter
:
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', (a, b) => {
console.log(a, b, this)
// Imprime: a b undefined
})
myEmitter.emit('event', 'a', 'b')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', (a, b) => {
console.log(a, b, this)
// Imprime: a b {}
})
myEmitter.emit('event', 'a', 'b')
Asíncrono vs. síncrono
El EventEmitter
llama a todos los listeners de forma síncrona en el orden en que fueron registrados. Esto asegura la secuencia adecuada de los eventos y ayuda a evitar condiciones de carrera y errores lógicos. Cuando es apropiado, las funciones de listener pueden cambiar a un modo de operación asíncrono usando los métodos setImmediate()
o process.nextTick()
:
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('esto sucede asíncronamente')
})
})
myEmitter.emit('event', 'a', 'b')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('esto sucede asíncronamente')
})
})
myEmitter.emit('event', 'a', 'b')
Manejar eventos solo una vez
Cuando un listener se registra usando el método eventEmitter.on()
, ese listener es invocado cada vez que se emite el evento nombrado.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
let m = 0
myEmitter.on('event', () => {
console.log(++m)
})
myEmitter.emit('event')
// Imprime: 1
myEmitter.emit('event')
// Imprime: 2
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
let m = 0
myEmitter.on('event', () => {
console.log(++m)
})
myEmitter.emit('event')
// Imprime: 1
myEmitter.emit('event')
// Imprime: 2
Usando el método eventEmitter.once()
, es posible registrar un listener que se llama como máximo una vez para un evento en particular. Una vez que se emite el evento, el listener se da de baja y luego se llama.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
let m = 0
myEmitter.once('event', () => {
console.log(++m)
})
myEmitter.emit('event')
// Imprime: 1
myEmitter.emit('event')
// Ignorado
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
let m = 0
myEmitter.once('event', () => {
console.log(++m)
})
myEmitter.emit('event')
// Imprime: 1
myEmitter.emit('event')
// Ignorado
Eventos de error
Cuando ocurre un error dentro de una instancia de EventEmitter
, la acción típica es que se emita un evento 'error'
. Estos se tratan como casos especiales dentro de Node.js.
Si un EventEmitter
no tiene al menos un oyente registrado para el evento 'error'
, y se emite un evento 'error'
, el error se lanza, se imprime un rastreo de pila y el proceso de Node.js sale.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('¡Ups!'))
// Lanza y bloquea Node.js
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('¡Ups!'))
// Lanza y bloquea Node.js
Para evitar que el proceso de Node.js se bloquee, se puede usar el módulo domain
. (Sin embargo, tenga en cuenta que el módulo node:domain
está obsoleto).
Como práctica recomendada, siempre se deben agregar oyentes para los eventos 'error'
.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
console.error('¡Ups! hubo un error')
})
myEmitter.emit('error', new Error('¡Ups!'))
// Imprime: ¡Ups! hubo un error
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
console.error('¡Ups! hubo un error')
})
myEmitter.emit('error', new Error('¡Ups!'))
// Imprime: ¡Ups! hubo un error
Es posible monitorear los eventos 'error'
sin consumir el error emitido instalando un oyente usando el símbolo events.errorMonitor
.
import { EventEmitter, errorMonitor } from 'node:events'
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('¡Ups!'))
// Aún lanza y bloquea Node.js
const { EventEmitter, errorMonitor } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('¡Ups!'))
// Aún lanza y bloquea Node.js
Capturar rechazos de promesas
Usar funciones async
con manejadores de eventos es problemático, porque puede llevar a un rechazo no manejado en caso de una excepción lanzada:
import { EventEmitter } from 'node:events'
const ee = new EventEmitter()
ee.on('something', async value => {
throw new Error('kaboom')
})
const EventEmitter = require('node:events')
const ee = new EventEmitter()
ee.on('something', async value => {
throw new Error('kaboom')
})
La opción captureRejections
en el constructor EventEmitter
o el cambio de configuración global cambian este comportamiento, instalando un manejador .then(undefined, handler)
en la Promise
. Este manejador enruta la excepción de forma asíncrona al método Symbol.for('nodejs.rejection')
si existe uno, o al manejador de eventos 'error'
si no hay ninguno.
import { EventEmitter } from 'node:events'
const ee1 = new EventEmitter({ captureRejections: true })
ee1.on('something', async value => {
throw new Error('kaboom')
})
ee1.on('error', console.log)
const ee2 = new EventEmitter({ captureRejections: true })
ee2.on('something', async value => {
throw new Error('kaboom')
})
ee2[Symbol.for('nodejs.rejection')] = console.log
const EventEmitter = require('node:events')
const ee1 = new EventEmitter({ captureRejections: true })
ee1.on('something', async value => {
throw new Error('kaboom')
})
ee1.on('error', console.log)
const ee2 = new EventEmitter({ captureRejections: true })
ee2.on('something', async value => {
throw new Error('kaboom')
})
ee2[Symbol.for('nodejs.rejection')] = console.log
Configurar events.captureRejections = true
cambiará el valor predeterminado para todas las nuevas instancias de EventEmitter
.
import { EventEmitter } from 'node:events'
EventEmitter.captureRejections = true
const ee1 = new EventEmitter()
ee1.on('something', async value => {
throw new Error('kaboom')
})
ee1.on('error', console.log)
const events = require('node:events')
events.captureRejections = true
const ee1 = new events.EventEmitter()
ee1.on('something', async value => {
throw new Error('kaboom')
})
ee1.on('error', console.log)
Los eventos 'error'
que son generados por el comportamiento captureRejections
no tienen un manejador catch para evitar bucles de error infinitos: la recomendación es no usar funciones async
como manejadores de eventos 'error'
.
Clase: EventEmitter
[Historial]
Versión | Cambios |
---|---|
v13.4.0, v12.16.0 | Se añadió la opción captureRejections. |
v0.1.26 | Añadido en: v0.1.26 |
La clase EventEmitter
es definida y expuesta por el módulo node:events
:
import { EventEmitter } from 'node:events'
const EventEmitter = require('node:events')
Todos los EventEmitter
emiten el evento 'newListener'
cuando se añaden nuevos listeners y 'removeListener'
cuando se eliminan listeners existentes.
Soporta la siguiente opción:
captureRejections
<boolean> Habilita la captura automática de rechazos de promesas. Predeterminado:false
.
Evento: 'newListener'
Añadido en: v0.1.26
eventName
<string> | <symbol> El nombre del evento que se está escuchandolistener
<Function> La función manejadora del evento
La instancia de EventEmitter
emitirá su propio evento 'newListener'
antes de que un listener sea añadido a su array interno de listeners.
Los listeners registrados para el evento 'newListener'
reciben el nombre del evento y una referencia al listener que se está añadiendo.
El hecho de que el evento se active antes de añadir el listener tiene un efecto secundario sutil pero importante: cualquier listener adicional registrado para el mismo nombre
dentro del callback de 'newListener'
se inserta antes del listener que está en proceso de ser añadido.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
// Solo hacer esto una vez para no entrar en un bucle infinito
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Inserta un nuevo listener al frente
myEmitter.on('event', () => {
console.log('B')
})
}
})
myEmitter.on('event', () => {
console.log('A')
})
myEmitter.emit('event')
// Imprime:
// B
// A
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
// Solo hacer esto una vez para no entrar en un bucle infinito
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Inserta un nuevo listener al frente
myEmitter.on('event', () => {
console.log('B')
})
}
})
myEmitter.on('event', () => {
console.log('A')
})
myEmitter.emit('event')
// Imprime:
// B
// A
Evento: 'removeListener'
[Historial]
Versión | Cambios |
---|---|
v6.1.0, v4.7.0 | Para los listeners adjuntos usando .once() , el argumento listener ahora produce la función listener original. |
v0.9.3 | Añadido en: v0.9.3 |
eventName
<string> | <symbol> El nombre del eventolistener
<Function> La función de controlador de eventos
El evento 'removeListener'
se emite después de que se elimina el listener
.
emitter.addListener(eventName, listener)
Añadido en: v0.1.26
eventName
<string> | <symbol>listener
<Function>
Alias para emitter.on(eventName, listener)
.
emitter.emit(eventName[, ...args])
Agregado en: v0.1.26
Llama sincrónicamente a cada uno de los listeners registrados para el evento llamado eventName
, en el orden en que fueron registrados, pasando los argumentos suministrados a cada uno.
Devuelve true
si el evento tenía listeners, false
en caso contrario.
import { EventEmitter } from 'node:events'
const myEmitter = new EventEmitter()
// Primer listener
myEmitter.on('event', function firstListener() {
console.log('¡Hola! primer listener')
})
// Segundo listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`evento con parámetros ${arg1}, ${arg2} en el segundo listener`)
})
// Tercer listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ')
console.log(`evento con parámetros ${parameters} en el tercer listener`)
})
console.log(myEmitter.listeners('event'))
myEmitter.emit('event', 1, 2, 3, 4, 5)
// Imprime:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// ¡Hola! primer listener
// evento con parámetros 1, 2 en el segundo listener
// evento con parámetros 1, 2, 3, 4, 5 en el tercer listener
const EventEmitter = require('node:events')
const myEmitter = new EventEmitter()
// Primer listener
myEmitter.on('event', function firstListener() {
console.log('¡Hola! primer listener')
})
// Segundo listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`evento con parámetros ${arg1}, ${arg2} en el segundo listener`)
})
// Tercer listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ')
console.log(`evento con parámetros ${parameters} en el tercer listener`)
})
console.log(myEmitter.listeners('event'))
myEmitter.emit('event', 1, 2, 3, 4, 5)
// Imprime:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// ¡Hola! primer listener
// evento con parámetros 1, 2 en el segundo listener
// evento con parámetros 1, 2, 3, 4, 5 en el tercer listener
emitter.eventNames()
Agregado en: v6.0.0
- Devuelve: <Array>
Devuelve un array que enumera los eventos para los que el emisor ha registrado listeners. Los valores en el array son cadenas o Symbol
s.
import { EventEmitter } from 'node:events'
const myEE = new EventEmitter()
myEE.on('foo', () => {})
myEE.on('bar', () => {})
const sym = Symbol('symbol')
myEE.on(sym, () => {})
console.log(myEE.eventNames())
// Imprime: [ 'foo', 'bar', Symbol(symbol) ]
const EventEmitter = require('node:events')
const myEE = new EventEmitter()
myEE.on('foo', () => {})
myEE.on('bar', () => {})
const sym = Symbol('symbol')
myEE.on(sym, () => {})
console.log(myEE.eventNames())
// Imprime: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
Agregado en: v1.0.0
- Devuelve: <integer>
Devuelve el valor máximo actual de listeners para el EventEmitter
que se establece mediante emitter.setMaxListeners(n)
o que por defecto es events.defaultMaxListeners
.
emitter.listenerCount(eventName[, listener])
[Historial]
Versión | Cambios |
---|---|
v19.8.0, v18.16.0 | Se agregó el argumento listener . |
v3.2.0 | Se agregó en: v3.2.0 |
eventName
<string> | <symbol> El nombre del evento que se está escuchando.listener
<Function> La función de controlador de eventos.- Devuelve: <integer>
Devuelve el número de listeners que escuchan el evento llamado eventName
. Si se proporciona listener
, devolverá cuántas veces se encuentra el listener en la lista de listeners del evento.
emitter.listeners(eventName)
[Historial]
Versión | Cambios |
---|---|
v7.0.0 | Para los listeners adjuntos utilizando .once() , ahora devuelve los listeners originales en lugar de las funciones de envoltura. |
v0.1.26 | Se agregó en: v0.1.26 |
eventName
<string> | <symbol>- Devuelve: <Function[]>
Devuelve una copia del array de listeners para el evento llamado eventName
.
server.on('connection', stream => {
console.log('¡alguien se conectó!')
})
console.log(util.inspect(server.listeners('connection')))
// Imprime: [ [Function] ]
emitter.off(eventName, listener)
Agregado en: v10.0.0
eventName
<string> | <symbol>listener
<Function>- Devuelve: <EventEmitter>
Alias para emitter.removeListener()
.
emitter.on(eventName, listener)
Agregado en: v0.1.101
eventName
<string> | <symbol> El nombre del evento.listener
<Function> La función de callback- Devuelve: <EventEmitter>
Agrega la función listener
al final del array de listeners para el evento llamado eventName
. No se realizan comprobaciones para ver si el listener
ya ha sido agregado. Múltiples llamadas pasando la misma combinación de eventName
y listener
resultarán en que el listener
sea agregado, y llamado, múltiples veces.
server.on('connection', stream => {
console.log('¡alguien se conectó!')
})
Devuelve una referencia al EventEmitter
, para que las llamadas puedan ser encadenadas.
Por defecto, los listeners de eventos son invocados en el orden en que son agregados. El método emitter.prependListener()
puede ser usado como una alternativa para agregar el listener de evento al principio del array de listeners.
import { EventEmitter } from 'node:events'
const myEE = new EventEmitter()
myEE.on('foo', () => console.log('a'))
myEE.prependListener('foo', () => console.log('b'))
myEE.emit('foo')
// Imprime:
// b
// a
const EventEmitter = require('node:events')
const myEE = new EventEmitter()
myEE.on('foo', () => console.log('a'))
myEE.prependListener('foo', () => console.log('b'))
myEE.emit('foo')
// Imprime:
// b
// a
emitter.once(eventName, listener)
Añadido en: v0.3.0
eventName
<string> | <symbol> El nombre del evento.listener
<Function> La función de callback.- Devuelve: <EventEmitter>
Añade una función listener
de una sola vez para el evento llamado eventName
. La próxima vez que se active eventName
, este listener se elimina y luego se invoca.
server.once('connection', stream => {
console.log('¡Ah, tenemos nuestro primer usuario!')
})
Devuelve una referencia a EventEmitter
, para que las llamadas se puedan encadenar.
Por defecto, los listeners de eventos se invocan en el orden en que se añaden. El método emitter.prependOnceListener()
se puede usar como alternativa para añadir el listener de eventos al principio del array de listeners.
import { EventEmitter } from 'node:events'
const myEE = new EventEmitter()
myEE.once('foo', () => console.log('a'))
myEE.prependOnceListener('foo', () => console.log('b'))
myEE.emit('foo')
// Imprime:
// b
// a
const EventEmitter = require('node:events')
const myEE = new EventEmitter()
myEE.once('foo', () => console.log('a'))
myEE.prependOnceListener('foo', () => console.log('b'))
myEE.emit('foo')
// Imprime:
// b
// a
emitter.prependListener(eventName, listener)
Agregado en: v6.0.0
eventName
<string> | <symbol> El nombre del evento.listener
<Function> La función de retorno de llamada.- Devuelve: <EventEmitter>
Agrega la función listener
al principio del array de listeners para el evento llamado eventName
. No se realizan comprobaciones para ver si el listener
ya ha sido añadido. Múltiples llamadas que pasan la misma combinación de eventName
y listener
resultarán en que el listener
se añada, y se llame, varias veces.
server.prependListener('connection', stream => {
console.log('¡alguien se ha conectado!')
})
Devuelve una referencia al EventEmitter
, de modo que las llamadas se puedan encadenar.
emitter.prependOnceListener(eventName, listener)
Agregado en: v6.0.0
eventName
<string> | <symbol> El nombre del evento.listener
<Function> La función de callback- Devuelve: <EventEmitter>
Agrega una función listener
de una sola vez para el evento llamado eventName
al principio del array de listeners. La próxima vez que se active eventName
, este listener se elimina y luego se invoca.
server.prependOnceListener('connection', stream => {
console.log('¡Ah, tenemos nuestro primer usuario!')
})
Devuelve una referencia a EventEmitter
, para que las llamadas puedan encadenarse.
emitter.removeAllListeners([eventName])
Agregado en: v0.1.26
eventName
<string> | <symbol>- Devuelve: <EventEmitter>
Elimina todos los listeners, o aquellos del eventName
especificado.
Es una mala práctica eliminar listeners agregados en otro lugar del código, particularmente cuando la instancia de EventEmitter
fue creada por algún otro componente o módulo (p. ej., sockets o flujos de archivos).
Devuelve una referencia a EventEmitter
, para que las llamadas puedan encadenarse.
emitter.removeListener(eventName, listener)
Agregado en: v0.1.26
eventName
<string> | <symbol>listener
<Function>- Devuelve: <EventEmitter>
Elimina el listener
especificado del arreglo de listeners para el evento llamado eventName
.
const callback = stream => {
console.log('¡alguien se conectó!')
}
server.on('connection', callback)
// ...
server.removeListener('connection', callback)
removeListener()
eliminará, como máximo, una instancia de un listener del arreglo de listeners. Si algún listener se ha añadido varias veces al arreglo de listeners para el eventName
especificado, entonces removeListener()
debe llamarse varias veces para eliminar cada instancia.
Una vez que se emite un evento, todos los listeners adjuntos a él en el momento de la emisión se llaman en orden. Esto implica que cualquier llamada a removeListener()
o removeAllListeners()
después de la emisión y antes de que el último listener termine la ejecución no los eliminará de emit()
en progreso. Los eventos posteriores se comportan como se espera.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
const callbackA = () => {
console.log('A')
myEmitter.removeListener('event', callbackB)
}
const callbackB = () => {
console.log('B')
}
myEmitter.on('event', callbackA)
myEmitter.on('event', callbackB)
// callbackA elimina el listener callbackB pero todavía será llamado.
// Arreglo interno de listeners al momento de emitir [callbackA, callbackB]
myEmitter.emit('event')
// Imprime:
// A
// B
// callbackB ahora está eliminado.
// Arreglo interno de listeners [callbackA]
myEmitter.emit('event')
// Imprime:
// A
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
const callbackA = () => {
console.log('A')
myEmitter.removeListener('event', callbackB)
}
const callbackB = () => {
console.log('B')
}
myEmitter.on('event', callbackA)
myEmitter.on('event', callbackB)
// callbackA elimina el listener callbackB pero todavía será llamado.
// Arreglo interno de listeners al momento de emitir [callbackA, callbackB]
myEmitter.emit('event')
// Imprime:
// A
// B
// callbackB ahora está eliminado.
// Arreglo interno de listeners [callbackA]
myEmitter.emit('event')
// Imprime:
// A
Debido a que los listeners se gestionan utilizando un arreglo interno, llamar a esto cambiará los índices de posición de cualquier listener registrado después del listener que se está eliminando. Esto no afectará el orden en que se llaman los listeners, pero significa que cualquier copia del arreglo de listeners devuelto por el método emitter.listeners()
deberá ser recreada.
Cuando se ha añadido una única función como controlador varias veces para un solo evento (como en el ejemplo siguiente), removeListener()
eliminará la instancia añadida más recientemente. En el ejemplo se elimina el listener once('ping')
:
import { EventEmitter } from 'node:events'
const ee = new EventEmitter()
function pong() {
console.log('pong')
}
ee.on('ping', pong)
ee.once('ping', pong)
ee.removeListener('ping', pong)
ee.emit('ping')
ee.emit('ping')
const EventEmitter = require('node:events')
const ee = new EventEmitter()
function pong() {
console.log('pong')
}
ee.on('ping', pong)
ee.once('ping', pong)
ee.removeListener('ping', pong)
ee.emit('ping')
ee.emit('ping')
Devuelve una referencia al EventEmitter
, para que las llamadas se puedan encadenar.
emitter.setMaxListeners(n)
Agregado en: v0.3.5
n
<integer>- Devuelve: <EventEmitter>
De forma predeterminada, los EventEmitter
imprimirán una advertencia si se agregan más de 10
listeners para un evento en particular. Este es un valor predeterminado útil que ayuda a encontrar fugas de memoria. El método emitter.setMaxListeners()
permite modificar el límite para esta instancia específica de EventEmitter
. El valor se puede establecer en Infinity
(o 0
) para indicar un número ilimitado de listeners.
Devuelve una referencia al EventEmitter
, de modo que las llamadas se puedan encadenar.
emitter.rawListeners(eventName)
Agregado en: v9.4.0
eventName
<string> | <symbol>- Devuelve: <Function[]>
Devuelve una copia del array de listeners para el evento llamado eventName
, incluyendo cualquier envoltorio (como los creados por .once()
).
import { EventEmitter } from 'node:events'
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// Devuelve un nuevo array con una función `onceWrapper` que tiene una propiedad
// `listener` que contiene el listener original vinculado anteriormente
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// Imprime "log once" en la consola y no desvincula el evento `once`
logFnWrapper.listener()
// Imprime "log once" en la consola y elimina el listener
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// Devolverá un nuevo array con una única función vinculada por `.on()` anteriormente
const newListeners = emitter.rawListeners('log')
// Imprime "log persistently" dos veces
newListeners[0]()
emitter.emit('log')
const EventEmitter = require('node:events')
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// Devuelve un nuevo array con una función `onceWrapper` que tiene una propiedad
// `listener` que contiene el listener original vinculado anteriormente
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// Imprime "log once" en la consola y no desvincula el evento `once`
logFnWrapper.listener()
// Imprime "log once" en la consola y elimina el listener
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// Devolverá un nuevo array con una única función vinculada por `.on()` anteriormente
const newListeners = emitter.rawListeners('log')
// Imprime "log persistently" dos veces
newListeners[0]()
emitter.emit('log')
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
[Historial]
Versión | Cambios |
---|---|
v17.4.0, v16.14.0 | Ya no es experimental. |
v13.4.0, v12.16.0 | Añadido en: v13.4.0, v12.16.0 |
El método Symbol.for('nodejs.rejection')
se llama en caso de que ocurra un rechazo de promesa al emitir un evento y captureRejections
esté habilitado en el emisor. Es posible usar events.captureRejectionSymbol
en lugar de Symbol.for('nodejs.rejection')
.
import { EventEmitter, captureRejectionSymbol } from 'node:events'
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true })
}
[captureRejectionSymbol](err, event, ...args) {
console.log('se produjo un rechazo para', event, 'con', err, ...args)
this.destroy(err)
}
destroy(err) {
// Destruir el recurso aquí.
}
}
const { EventEmitter, captureRejectionSymbol } = require('node:events')
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true })
}
[captureRejectionSymbol](err, event, ...args) {
console.log('se produjo un rechazo para', event, 'con', err, ...args)
this.destroy(err)
}
destroy(err) {
// Destruir el recurso aquí.
}
}
events.defaultMaxListeners
Agregado en: v0.11.2
De forma predeterminada, se puede registrar un máximo de 10
listeners para cualquier evento individual. Este límite se puede cambiar para instancias individuales de EventEmitter
utilizando el método emitter.setMaxListeners(n)
. Para cambiar el valor predeterminado para todas las instancias de EventEmitter
, se puede utilizar la propiedad events.defaultMaxListeners
. Si este valor no es un número positivo, se lanza un RangeError
.
Tenga cuidado al establecer events.defaultMaxListeners
porque el cambio afecta a todas las instancias de EventEmitter
, incluidas las que se crearon antes de que se realizara el cambio. Sin embargo, llamar a emitter.setMaxListeners(n)
sigue teniendo precedencia sobre events.defaultMaxListeners
.
Este no es un límite estricto. La instancia de EventEmitter
permitirá que se agreguen más listeners, pero generará una advertencia de seguimiento en stderr que indica que se ha detectado una "posible fuga de memoria de EventEmitter". Para cualquier EventEmitter
individual, los métodos emitter.getMaxListeners()
y emitter.setMaxListeners()
se pueden utilizar para evitar temporalmente esta advertencia:
defaultMaxListeners
no tiene efecto en las instancias de AbortSignal
. Si bien todavía es posible utilizar emitter.setMaxListeners(n)
para establecer un límite de advertencia para instancias individuales de AbortSignal
, de forma predeterminada las instancias de AbortSignal
no generarán ninguna advertencia.
import { EventEmitter } from 'node:events'
const emitter = new EventEmitter()
emitter.setMaxListeners(emitter.getMaxListeners() + 1)
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0))
})
const EventEmitter = require('node:events')
const emitter = new EventEmitter()
emitter.setMaxListeners(emitter.getMaxListeners() + 1)
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0))
})
El indicador de línea de comandos --trace-warnings
se puede usar para mostrar el rastreo de la pila de dichas advertencias.
La advertencia emitida se puede inspeccionar con process.on('warning')
y tendrá las propiedades adicionales emitter
, type
y count
, que hacen referencia a la instancia del emisor de eventos, el nombre del evento y el número de listeners adjuntos, respectivamente. Su propiedad name
se establece en 'MaxListenersExceededWarning'
.
events.errorMonitor
Agregado en: v13.6.0, v12.17.0
Este símbolo se utilizará para instalar un listener solo para monitorear eventos 'error'
. Los listeners instalados usando este símbolo se llaman antes de que se llamen los listeners regulares 'error'
.
La instalación de un listener utilizando este símbolo no cambia el comportamiento una vez que se emite un evento 'error'
. Por lo tanto, el proceso aún fallará si no se instala ningún listener regular 'error'
.
events.getEventListeners(emitterOrTarget, eventName)
Agregado en: v15.2.0, v14.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>eventName
<string> | <symbol>- Devuelve: <Function[]>
Devuelve una copia de la matriz de listeners para el evento llamado eventName
.
Para los EventEmitter
, esto se comporta exactamente igual que llamar a .listeners
en el emisor.
Para EventTarget
, esta es la única forma de obtener los listeners de eventos para el objetivo del evento. Esto es útil para fines de depuración y diagnóstico.
import { getEventListeners, EventEmitter } from 'node:events'
{
const ee = new EventEmitter()
const listener = () => console.log('Events are fun')
ee.on('foo', listener)
console.log(getEventListeners(ee, 'foo')) // [ [Function: listener] ]
}
{
const et = new EventTarget()
const listener = () => console.log('Events are fun')
et.addEventListener('foo', listener)
console.log(getEventListeners(et, 'foo')) // [ [Function: listener] ]
}
const { getEventListeners, EventEmitter } = require('node:events')
{
const ee = new EventEmitter()
const listener = () => console.log('Events are fun')
ee.on('foo', listener)
console.log(getEventListeners(ee, 'foo')) // [ [Function: listener] ]
}
{
const et = new EventTarget()
const listener = () => console.log('Events are fun')
et.addEventListener('foo', listener)
console.log(getEventListeners(et, 'foo')) // [ [Function: listener] ]
}
events.getMaxListeners(emitterOrTarget)
Agregado en: v19.9.0, v18.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>- Devuelve: <number>
Devuelve la cantidad máxima de listeners establecida actualmente.
Para EventEmitter
s, esto se comporta exactamente igual que llamar a .getMaxListeners
en el emisor.
Para EventTarget
s, esta es la única forma de obtener el máximo de listeners de eventos para el target de eventos. Si el número de manejadores de eventos en un solo EventTarget excede el máximo establecido, el EventTarget imprimirá una advertencia.
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events'
{
const ee = new EventEmitter()
console.log(getMaxListeners(ee)) // 10
setMaxListeners(11, ee)
console.log(getMaxListeners(ee)) // 11
}
{
const et = new EventTarget()
console.log(getMaxListeners(et)) // 10
setMaxListeners(11, et)
console.log(getMaxListeners(et)) // 11
}
const { getMaxListeners, setMaxListeners, EventEmitter } = require('node:events')
{
const ee = new EventEmitter()
console.log(getMaxListeners(ee)) // 10
setMaxListeners(11, ee)
console.log(getMaxListeners(ee)) // 11
}
{
const et = new EventTarget()
console.log(getMaxListeners(et)) // 10
setMaxListeners(11, et)
console.log(getMaxListeners(et)) // 11
}
events.once(emisor, nombre[, opciones])
[Historial]
Versión | Cambios |
---|---|
v15.0.0 | Ahora se soporta la opción signal . |
v11.13.0, v10.16.0 | Añadido en: v11.13.0, v10.16.0 |
emisor
<EventEmitter>opciones
<Object>signal
<AbortSignal> Puede usarse para cancelar la espera del evento.
Devuelve: <Promise>
Crea una Promise
que se cumple cuando el EventEmitter
emite el evento dado o que se rechaza si el EventEmitter
emite 'error'
mientras espera. La Promise
se resolverá con un array de todos los argumentos emitidos al evento dado.
Este método es intencionalmente genérico y funciona con la interfaz EventTarget de la plataforma web, que no tiene semántica especial para el evento 'error'
y no escucha al evento 'error'
.
import { once, EventEmitter } from 'node:events'
import process from 'node:process'
const ee = new EventEmitter()
process.nextTick(() => {
ee.emit('myevent', 42)
})
const [value] = await once(ee, 'myevent')
console.log(value)
const err = new Error('kaboom')
process.nextTick(() => {
ee.emit('error', err)
})
try {
await once(ee, 'myevent')
} catch (err) {
console.error('error happened', err)
}
const { once, EventEmitter } = require('node:events')
async function run() {
const ee = new EventEmitter()
process.nextTick(() => {
ee.emit('myevent', 42)
})
const [value] = await once(ee, 'myevent')
console.log(value)
const err = new Error('kaboom')
process.nextTick(() => {
ee.emit('error', err)
})
try {
await once(ee, 'myevent')
} catch (err) {
console.error('error happened', err)
}
}
run()
El manejo especial del evento 'error'
solo se usa cuando events.once()
se usa para esperar otro evento. Si events.once()
se usa para esperar el propio evento 'error
', entonces se trata como cualquier otro tipo de evento sin manejo especial:
import { EventEmitter, once } from 'node:events'
const ee = new EventEmitter()
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch(err => console.error('error', err.message))
ee.emit('error', new Error('boom'))
// Imprime: ok boom
const { EventEmitter, once } = require('node:events')
const ee = new EventEmitter()
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch(err => console.error('error', err.message))
ee.emit('error', new Error('boom'))
// Imprime: ok boom
Se puede usar un <AbortSignal> para cancelar la espera del evento:
import { EventEmitter, once } from 'node:events'
const ee = new EventEmitter()
const ac = new AbortController()
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal })
console.log('event emitted!')
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!')
} else {
console.error('There was an error', error.message)
}
}
}
foo(ee, 'foo', ac.signal)
ac.abort() // Imprime: Waiting for the event was canceled!
const { EventEmitter, once } = require('node:events')
const ee = new EventEmitter()
const ac = new AbortController()
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal })
console.log('event emitted!')
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!')
} else {
console.error('There was an error', error.message)
}
}
}
foo(ee, 'foo', ac.signal)
ac.abort() // Imprime: Waiting for the event was canceled!
Esperando múltiples eventos emitidos en process.nextTick()
Existe un caso límite que vale la pena señalar al usar la función events.once()
para esperar múltiples eventos emitidos en el mismo lote de operaciones de process.nextTick()
, o cada vez que se emiten múltiples eventos de forma síncrona. Específicamente, debido a que la cola process.nextTick()
se vacía antes de la cola de microtareas Promise
, y debido a que EventEmitter
emite todos los eventos de forma síncrona, es posible que events.once()
pierda un evento.
import { EventEmitter, once } from 'node:events'
import process from 'node:process'
const myEE = new EventEmitter()
async function foo() {
await once(myEE, 'bar')
console.log('bar')
// Esta Promise nunca se resolverá porque el evento 'foo' ya se
// habrá emitido antes de que se cree la Promise.
await once(myEE, 'foo')
console.log('foo')
}
process.nextTick(() => {
myEE.emit('bar')
myEE.emit('foo')
})
foo().then(() => console.log('done'))
const { EventEmitter, once } = require('node:events')
const myEE = new EventEmitter()
async function foo() {
await once(myEE, 'bar')
console.log('bar')
// Esta Promise nunca se resolverá porque el evento 'foo' ya se
// habrá emitido antes de que se cree la Promise.
await once(myEE, 'foo')
console.log('foo')
}
process.nextTick(() => {
myEE.emit('bar')
myEE.emit('foo')
})
foo().then(() => console.log('done'))
Para capturar ambos eventos, crea cada una de las Promesas antes de esperar cualquiera de ellas, entonces se vuelve posible usar Promise.all()
, Promise.race()
, o Promise.allSettled()
:
import { EventEmitter, once } from 'node:events'
import process from 'node:process'
const myEE = new EventEmitter()
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')])
console.log('foo', 'bar')
}
process.nextTick(() => {
myEE.emit('bar')
myEE.emit('foo')
})
foo().then(() => console.log('done'))
const { EventEmitter, once } = require('node:events')
const myEE = new EventEmitter()
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')])
console.log('foo', 'bar')
}
process.nextTick(() => {
myEE.emit('bar')
myEE.emit('foo')
})
foo().then(() => console.log('done'))
events.captureRejections
[Historial]
Versión | Cambios |
---|---|
v17.4.0, v16.14.0 | Ya no es experimental. |
v13.4.0, v12.16.0 | Añadido en: v13.4.0, v12.16.0 |
Valor: <boolean>
Cambia la opción captureRejections
predeterminada en todos los nuevos objetos EventEmitter
.
events.captureRejectionSymbol
[Historial]
Versión | Cambios |
---|---|
v17.4.0, v16.14.0 | Ya no es experimental. |
v13.4.0, v12.16.0 | Añadido en: v13.4.0, v12.16.0 |
Valor: Symbol.for('nodejs.rejection')
Mira cómo escribir un manejador de rechazos personalizado.
events.listenerCount(emitter, eventName)
Añadido en: v0.9.12
Obsoleto desde: v3.2.0
[Estable: 0 - Obsoleto]
Estable: 0 Estabilidad: 0 - Obsoleto: Use emitter.listenerCount()
en su lugar.
emitter
<EventEmitter> El emisor a consultareventName
<string> | <symbol> El nombre del evento
Un método de clase que devuelve el número de listeners para el eventName
dado registrado en el emitter
dado.
import { EventEmitter, listenerCount } from 'node:events'
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// Imprime: 2
const { EventEmitter, listenerCount } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// Imprime: 2
events.on(emisor, nombreEvento[, opciones])
[Historial]
Versión | Cambios |
---|---|
v22.0.0, v20.13.0 | Soporte para opciones highWaterMark y lowWaterMark , por consistencia. Las opciones antiguas siguen siendo compatibles. |
v20.0.0 | Ahora se admiten las opciones close , highWatermark y lowWatermark . |
v13.6.0, v12.16.0 | Añadido en: v13.6.0, v12.16.0 |
emisor
<EventEmitter>nombreEvento
<string> | <symbol> El nombre del evento que se está escuchandoopciones
<Object>signal
<AbortSignal> Se puede utilizar para cancelar eventos en espera.close
- <string[]> Nombres de los eventos que finalizarán la iteración.highWaterMark
- <integer> Predeterminado:Number.MAX_SAFE_INTEGER
. La marca de agua alta. El emisor se pausa cada vez que el tamaño de los eventos almacenados en búfer es mayor que ella. Solo se admite en emisores que implementan los métodospause()
yresume()
.lowWaterMark
- <integer> Predeterminado:1
. La marca de agua baja. El emisor se reanuda cada vez que el tamaño de los eventos almacenados en búfer es inferior a ella. Solo se admite en emisores que implementan los métodospause()
yresume()
.
Devuelve: <AsyncIterator> que itera los eventos
nombreEvento
emitidos por elemisor
import { on, EventEmitter } from 'node:events'
import process from 'node:process'
const ee = new EventEmitter()
// Emitir más tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const evento of on(ee, 'foo')) {
// La ejecución de este bloque interno es síncrona y procesa un
// evento a la vez (incluso con await). No usar si se requiere
// ejecución concurrente.
console.log(evento) // Imprime ['bar'] [42]
}
// Inalcanzable aquí
const { on, EventEmitter } = require('node:events')
;(async () => {
const ee = new EventEmitter()
// Emitir más tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const evento of on(ee, 'foo')) {
// La ejecución de este bloque interno es síncrona y procesa un
// evento a la vez (incluso con await). No usar si se requiere
// ejecución concurrente.
console.log(evento) // Imprime ['bar'] [42]
}
// Inalcanzable aquí
})()
Devuelve un AsyncIterator
que itera los eventos nombreEvento
. Lanzará un error si el EventEmitter
emite 'error'
. Elimina todos los listeners al salir del bucle. El valor
devuelto por cada iteración es un array compuesto por los argumentos del evento emitido.
Se puede utilizar un <AbortSignal> para cancelar la espera de eventos:
import { on, EventEmitter } from 'node:events'
import process from 'node:process'
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// Emitir más tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const evento of on(ee, 'foo', { signal: ac.signal })) {
// La ejecución de este bloque interno es síncrona y procesa un
// evento a la vez (incluso con await). No usar si se requiere
// ejecución concurrente.
console.log(evento) // Imprime ['bar'] [42]
}
// Inalcanzable aquí
})()
process.nextTick(() => ac.abort())
const { on, EventEmitter } = require('node:events')
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// Emitir más tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const evento of on(ee, 'foo', { signal: ac.signal })) {
// La ejecución de este bloque interno es síncrona y procesa un
// evento a la vez (incluso con await). No usar si se requiere
// ejecución concurrente.
console.log(evento) // Imprime ['bar'] [42]
}
// Inalcanzable aquí
})()
process.nextTick(() => ac.abort())
events.setMaxListeners(n[, ...eventTargets])
Agregado en: v15.4.0
n
<number> Un número no negativo. El número máximo de listeners por eventoEventTarget
....eventsTargets
<EventTarget[]> | <EventEmitter[]> Cero o más instancias de <EventTarget> o <EventEmitter>. Si no se especifica ninguno,n
se establece como el máximo predeterminado para todos los objetos <EventTarget> y <EventEmitter> recién creados.
import { setMaxListeners, EventEmitter } from 'node:events'
const target = new EventTarget()
const emitter = new EventEmitter()
setMaxListeners(5, target, emitter)
const { setMaxListeners, EventEmitter } = require('node:events')
const target = new EventTarget()
const emitter = new EventEmitter()
setMaxListeners(5, target, emitter)
events.addAbortListener(signal, listener)
Añadido en: v20.5.0, v18.18.0
[Estable: 1 - Experimental]
Estable: 1 Estabilidad: 1 - Experimental
signal
<AbortSignal>listener
<Function> | <EventListener>- Devuelve: <Disposable> Un Disposable que elimina el listener de
abort
.
Escucha una vez el evento abort
en la señal
proporcionada.
Escuchar el evento abort
en señales de aborto no es seguro y puede provocar fugas de recursos, ya que otro tercero con la señal puede llamar a e.stopImmediatePropagation()
. Desafortunadamente, Node.js no puede cambiar esto ya que violaría el estándar web. Además, la API original facilita olvidar eliminar los listeners.
Esta API permite utilizar de forma segura AbortSignal
s en las APIs de Node.js al resolver estos dos problemas, escuchando el evento de tal manera que stopImmediatePropagation
no impida que el listener se ejecute.
Devuelve un disposable para que se pueda dar de baja más fácilmente.
const { addAbortListener } = require('node:events')
function example(signal) {
let disposable
try {
signal.addEventListener('abort', e => e.stopImmediatePropagation())
disposable = addAbortListener(signal, e => {
// Hacer algo cuando se aborte la señal.
})
} finally {
disposable?.[Symbol.dispose]()
}
}
import { addAbortListener } from 'node:events'
function example(signal) {
let disposable
try {
signal.addEventListener('abort', e => e.stopImmediatePropagation())
disposable = addAbortListener(signal, e => {
// Hacer algo cuando se aborte la señal.
})
} finally {
disposable?.[Symbol.dispose]()
}
}
Clase: events.EventEmitterAsyncResource extends EventEmitter
Agregado en: v17.4.0, v16.14.0
Integra EventEmitter
con <AsyncResource> para EventEmitter
s que requieren seguimiento asíncrono manual. Específicamente, todos los eventos emitidos por instancias de events.EventEmitterAsyncResource
se ejecutarán dentro de su contexto asíncrono.
import { EventEmitterAsyncResource, EventEmitter } from 'node:events'
import { notStrictEqual, strictEqual } from 'node:assert'
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks'
// Las herramientas de seguimiento asíncrono identificarán esto como 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' })
// Los listeners de 'foo' se ejecutarán en el contexto asíncrono de EventEmitters.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// Los listeners de 'foo' en EventEmitters ordinarios que no rastrean el contexto asíncrono,
// sin embargo, se ejecutan en el mismo contexto asíncrono que el emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId)
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId)
})
Promise.resolve().then(() => {
ee1.emit('foo')
ee2.emit('foo')
})
const { EventEmitterAsyncResource, EventEmitter } = require('node:events')
const { notStrictEqual, strictEqual } = require('node:assert')
const { executionAsyncId, triggerAsyncId } = require('node:async_hooks')
// Las herramientas de seguimiento asíncrono identificarán esto como 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' })
// Los listeners de 'foo' se ejecutarán en el contexto asíncrono de EventEmitters.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// Los listeners de 'foo' en EventEmitters ordinarios que no rastrean el contexto asíncrono,
// sin embargo, se ejecutan en el mismo contexto asíncrono que el emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId)
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId)
})
Promise.resolve().then(() => {
ee1.emit('foo')
ee2.emit('foo')
})
La clase EventEmitterAsyncResource
tiene los mismos métodos y toma las mismas opciones que EventEmitter
y AsyncResource
mismos.
new events.EventEmitterAsyncResource([opciones])
opciones
<Objeto>captureRejections
<boolean> Habilita la captura automática del rechazo de promesas. Predeterminado:false
.name
<string> El tipo de evento asíncrono. Predeterminado:new.target.name
.triggerAsyncId
<number> El ID del contexto de ejecución que creó este evento asíncrono. Predeterminado:executionAsyncId()
.requireManualDestroy
<boolean> Si se establece entrue
, deshabilitaemitDestroy
cuando el objeto es recolectado por el recolector de basura. Por lo general, esto no necesita establecerse (incluso siemitDestroy
se llama manualmente), a menos que se recupere elasyncId
del recurso y se llame a la API sensibleemitDestroy
con él. Cuando se establece enfalse
, la llamadaemitDestroy
en la recolección de basura solo tendrá lugar si hay al menos un ganchodestroy
activo. Predeterminado:false
.
eventemitterasyncresource.asyncId
- Tipo: <número> El
asyncId
único asignado al recurso.
eventemitterasyncresource.asyncResource
- Tipo: El <AsyncResource> subyacente.
El objeto AsyncResource
devuelto tiene una propiedad eventEmitter
adicional que proporciona una referencia a este EventEmitterAsyncResource
.
eventemitterasyncresource.emitDestroy()
Llama a todos los ganchos destroy
. Esto solo debería llamarse una vez. Se generará un error si se llama más de una vez. Esto debe llamarse manualmente. Si se deja que el recurso sea recolectado por el GC, los ganchos destroy
nunca serán llamados.
eventemitterasyncresource.triggerAsyncId
- Tipo: <número> El mismo
triggerAsyncId
que se pasa al constructorAsyncResource
.
API EventTarget
y Event
[Historial]
Versión | Cambios |
---|---|
v16.0.0 | Se cambió el manejo de errores de EventTarget. |
v15.4.0 | Ya no es experimental. |
v15.0.0 | Las clases EventTarget y Event ahora están disponibles como globales. |
v14.5.0 | Añadido en: v14.5.0 |
Los objetos EventTarget
y Event
son una implementación específica de Node.js de la EventTarget
Web API que exponen algunas APIs centrales de Node.js.
const target = new EventTarget()
target.addEventListener('foo', event => {
console.log('¡El evento foo ocurrió!')
})
EventTarget
de Node.js vs. EventTarget
del DOM
Existen dos diferencias clave entre el EventTarget
de Node.js y la EventTarget
Web API:
NodeEventTarget
vs. EventEmitter
El objeto NodeEventTarget
implementa un subconjunto modificado de la API EventEmitter
que le permite emular estrechamente un EventEmitter
en ciertas situaciones. Un NodeEventTarget
no es una instancia de EventEmitter
y no se puede utilizar en lugar de un EventEmitter
en la mayoría de los casos.
Escucha de eventos
Los escuchas de eventos registrados para un tipo
de evento pueden ser funciones de JavaScript u objetos con una propiedad handleEvent
cuyo valor sea una función.
En cualquier caso, la función de controlador se invoca con el argumento event
que se pasa a la función eventTarget.dispatchEvent()
.
Se pueden utilizar funciones asíncronas como escuchas de eventos. Si una función de controlador asíncrona rechaza, el rechazo se captura y se maneja como se describe en el manejo de errores de EventTarget
.
Un error lanzado por una función de controlador no impide que se invoquen los otros controladores.
El valor de retorno de una función de controlador se ignora.
Los controladores siempre se invocan en el orden en que se agregaron.
Las funciones de controlador pueden mutar el objeto event
.
function handler1(event) {
console.log(event.type) // Imprime 'foo'
event.a = 1
}
async function handler2(event) {
console.log(event.type) // Imprime 'foo'
console.log(event.a) // Imprime 1
}
const handler3 = {
handleEvent(event) {
console.log(event.type) // Imprime 'foo'
},
}
const handler4 = {
async handleEvent(event) {
console.log(event.type) // Imprime 'foo'
},
}
const target = new EventTarget()
target.addEventListener('foo', handler1)
target.addEventListener('foo', handler2)
target.addEventListener('foo', handler3)
target.addEventListener('foo', handler4, { once: true })
Manejo de errores en EventTarget
Cuando un receptor de eventos registrado lanza una excepción (o devuelve una Promesa que se rechaza), por defecto, el error se trata como una excepción no capturada en process.nextTick()
. Esto significa que las excepciones no capturadas en EventTarget
terminarán el proceso de Node.js por defecto.
Lanzar una excepción dentro de un receptor de eventos no impedirá que se invoquen los demás manejadores registrados.
EventTarget
no implementa ningún manejo predeterminado especial para eventos de tipo 'error'
como EventEmitter
.
Actualmente, los errores se reenvían primero al evento process.on('error')
antes de llegar a process.on('uncaughtException')
. Este comportamiento está obsoleto y cambiará en una versión futura para alinear EventTarget
con otras API de Node.js. Cualquier código que dependa del evento process.on('error')
debe alinearse con el nuevo comportamiento.
Clase: Event
[Historial]
Versión | Cambios |
---|---|
v15.0.0 | La clase Event ahora está disponible a través del objeto global. |
v14.5.0 | Agregado en: v14.5.0 |
El objeto Event
es una adaptación de la Event
Web API. Las instancias son creadas internamente por Node.js.
event.bubbles
Añadido en: v14.5.0
- Tipo: <boolean> Siempre devuelve
false
.
Esto no se utiliza en Node.js y se proporciona únicamente para completar la información.
event.cancelBubble
Añadido en: v14.5.0
[Estable: 3 - Legado]
Estable: 3 Estabilidad: 3 - Legado: Use event.stopPropagation()
en su lugar.
- Tipo: <boolean>
Alias para event.stopPropagation()
si se establece en true
. Esto no se utiliza en Node.js y se proporciona únicamente para completar la información.
event.cancelable
Añadido en: v14.5.0
- Tipo: <boolean> Verdadero si el evento fue creado con la opción
cancelable
.
event.composed
Añadido en: v14.5.0
- Tipo: <boolean> Siempre devuelve
false
.
Esto no se utiliza en Node.js y se proporciona únicamente para completar la información.
event.composedPath()
Agregado en: v14.5.0
Devuelve un array que contiene el EventTarget
actual como la única entrada o vacío si el evento no está siendo despachado. Esto no se utiliza en Node.js y se proporciona únicamente para que esté completo.
event.currentTarget
Agregado en: v14.5.0
- Tipo: <EventTarget> El
EventTarget
que despacha el evento.
Alias para event.target
.
event.defaultPrevented
Agregado en: v14.5.0
- Tipo: <boolean>
Es true
si cancelable
es true
y se ha llamado a event.preventDefault()
.
event.eventPhase
Agregado en: v14.5.0
- Tipo: <number> Devuelve
0
mientras un evento no está siendo despachado,2
mientras está siendo despachado.
Esto no se utiliza en Node.js y se proporciona únicamente para que esté completo.
event.initEvent(type[, bubbles[, cancelable]])
Agregado en: v19.5.0
[Estable: 3 - Legado]
Estable: 3 Estabilidad: 3 - Legado: La especificación WHATWG lo considera obsoleto y los usuarios no deberían usarlo en absoluto.
Redundante con los constructores de eventos e incapaz de establecer composed
. Esto no se utiliza en Node.js y se proporciona únicamente para que esté completo.
event.isTrusted
Agregado en: v14.5.0
- Tipo: <boolean>
El evento "abort"
de <AbortSignal> se emite con isTrusted
establecido en true
. El valor es false
en todos los demás casos.
event.preventDefault()
Agregado en: v14.5.0
Establece la propiedad defaultPrevented
en true
si cancelable
es true
.
event.returnValue
Agregado en: v14.5.0
[Estable: 3 - Legado]
Estable: 3 Estabilidad: 3 - Legado: Utilice event.defaultPrevented
en su lugar.
- Tipo: <boolean> True si el evento no ha sido cancelado.
El valor de event.returnValue
siempre es lo opuesto de event.defaultPrevented
. Esto no se utiliza en Node.js y se proporciona puramente para estar completo.
event.srcElement
Agregado en: v14.5.0
[Estable: 3 - Legado]
Estable: 3 Estabilidad: 3 - Legado: Use event.target
en su lugar.
- Tipo: <EventTarget> El
EventTarget
que emite el evento.
Alias para event.target
.
event.stopImmediatePropagation()
Agregado en: v14.5.0
Detiene la invocación de los listeners de eventos después de que el actual se complete.
event.stopPropagation()
Agregado en: v14.5.0
Esto no se utiliza en Node.js y se proporciona puramente para completar la funcionalidad.
event.target
Agregado en: v14.5.0
- Tipo: <EventTarget> El
EventTarget
que emite el evento.
event.timeStamp
Agregado en: v14.5.0
- Tipo: <number>
La marca de tiempo en milisegundos cuando se creó el objeto Event
.
event.type
Agregado en: v14.5.0
- Tipo: <string>
El identificador del tipo de evento.
Clase: EventTarget
[Historial]
Versión | Cambios |
---|---|
v15.0.0 | La clase EventTarget ahora está disponible a través del objeto global. |
v14.5.0 | Añadido en: v14.5.0 |
eventTarget.addEventListener(type, listener[, options])
[Historial]
Versión | Cambios |
---|---|
v15.4.0 | Se agregó soporte para la opción signal . |
v14.5.0 | Añadido en: v14.5.0 |
type
<string>listener
<Function> | <EventListener>options
<Object>once
<boolean> Cuando estrue
, el listener se elimina automáticamente cuando se invoca por primera vez. Predeterminado:false
.passive
<boolean> Cuando estrue
, sirve como una sugerencia de que el listener no llamará al métodopreventDefault()
del objetoEvent
. Predeterminado:false
.capture
<boolean> No es utilizado directamente por Node.js. Añadido para la integridad de la API. Predeterminado:false
.signal
<AbortSignal> El listener se eliminará cuando se llame al métodoabort()
del objeto AbortSignal dado.
Agrega un nuevo controlador para el evento type
. Cualquier listener
dado se agrega solo una vez por type
y por valor de opción capture
.
Si la opción once
es true
, el listener
se elimina después de la próxima vez que se envíe un evento type
.
Node.js no utiliza la opción capture
de ninguna manera funcional más allá de rastrear los listeners de eventos registrados según la especificación EventTarget
. Específicamente, la opción capture
se utiliza como parte de la clave al registrar un listener
. Cualquier listener
individual se puede agregar una vez con capture = false
y una vez con capture = true
.
function handler(event) {}
const target = new EventTarget()
target.addEventListener('foo', handler, { capture: true }) // first
target.addEventListener('foo', handler, { capture: false }) // second
// Removes the second instance of handler
target.removeEventListener('foo', handler)
// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true })
eventTarget.dispatchEvent(event)
Agregado en: v14.5.0
event
<Event>- Devuelve: <boolean>
true
si el valor del atributocancelable
del evento es falso o no se invocó su métodopreventDefault()
, de lo contrario,false
.
Envía el event
a la lista de controladores para event.type
.
Los detectores de eventos registrados se invocan de forma síncrona en el orden en que se registraron.
eventTarget.removeEventListener(type, listener[, options])
Agregado en: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Remueve el listener
de la lista de controladores para el evento type
.
Clase: CustomEvent
[Historial]
Versión | Cambios |
---|---|
v23.0.0 | Ya no es experimental. |
v22.1.0, v20.13.0 | CustomEvent ahora es estable. |
v19.0.0 | Ya no está detrás del flag de CLI --experimental-global-customevent . |
v18.7.0, v16.17.0 | Agregado en: v18.7.0, v16.17.0 |
[Estable: 2 - Estable]
Estable: 2 Estabilidad: 2 - Estable
- Extiende: <Event>
El objeto CustomEvent
es una adaptación de la Web API CustomEvent
. Las instancias se crean internamente por Node.js.
event.detail
[Historial]
Versión | Cambios |
---|---|
v22.1.0, v20.13.0 | CustomEvent ahora es estable. |
v18.7.0, v16.17.0 | Agregado en: v18.7.0, v16.17.0 |
[Estable: 2 - Estable]
Estable: 2 Estabilidad: 2 - Estable
- Tipo: <any> Devuelve datos personalizados pasados al inicializar.
De solo lectura.
Clase: NodeEventTarget
Agregado en: v14.5.0
- Extiende: <EventTarget>
NodeEventTarget
es una extensión específica de Node.js para EventTarget
que emula un subconjunto de la API de EventEmitter
.
nodeEventTarget.addListener(type, listener)
Agregado en: v14.5.0
type
<string>listener
<Function> | <EventListener>- Devuelve: <EventTarget> this
Extensión específica de Node.js para la clase EventTarget
que emula la API equivalente de EventEmitter
. La única diferencia entre addListener()
y addEventListener()
es que addListener()
devolverá una referencia a EventTarget
.
nodeEventTarget.emit(type, arg)
Agregado en: v15.2.0
type
<string>arg
<any>- Devuelve: <boolean>
true
si existen listeners de eventos registrados para eltype
, de lo contrariofalse
.
Extensión específica de Node.js para la clase EventTarget
que despacha el arg
a la lista de manejadores para type
.
nodeEventTarget.eventNames()
Agregado en: v14.5.0
- Devuelve: <string[]>
Extensión específica de Node.js a la clase EventTarget
que devuelve un array de nombres type
de eventos para los que se han registrado listeners de eventos.
nodeEventTarget.listenerCount(type)
Agregado en: v14.5.0
Extensión específica de Node.js a la clase EventTarget
que devuelve el número de listeners de eventos registrados para el type
.
nodeEventTarget.setMaxListeners(n)
Agregado en: v14.5.0
n
<number>
Extensión específica de Node.js a la clase EventTarget
que establece el número máximo de listeners de eventos como n
.
nodeEventTarget.getMaxListeners()
Agregado en: v14.5.0
- Devuelve: <number>
Extensión específica de Node.js para la clase EventTarget
que devuelve el número máximo de escuchas de eventos.
nodeEventTarget.off(type, listener[, options])
Agregado en: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Devuelve: <EventTarget> this
Alias específico de Node.js para eventTarget.removeEventListener()
.
nodeEventTarget.on(type, listener)
Agregado en: v14.5.0
type
<string>listener
<Function> | <EventListener>- Devuelve: <EventTarget> this
Alias específico de Node.js para eventTarget.addEventListener()
.
nodeEventTarget.once(type, listener)
Agregado en: v14.5.0
type
<string>listener
<Function> | <EventListener>- Devuelve: <EventTarget> this
Extensión específica de Node.js a la clase EventTarget
que añade un listener once
para el type
de evento dado. Esto es equivalente a llamar a on
con la opción once
establecida en true
.
nodeEventTarget.removeAllListeners([type])
Agregado en: v14.5.0
type
<string>- Devuelve: <EventTarget> this
Extensión específica de Node.js para la clase EventTarget
. Si se especifica type
, elimina todos los listeners registrados para type
, de lo contrario, elimina todos los listeners registrados.
nodeEventTarget.removeListener(type, listener[, options])
Agregado en: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Devuelve: <EventTarget> this
Extensión específica de Node.js para la clase EventTarget
que elimina el listener
para el type
dado. La única diferencia entre removeListener()
y removeEventListener()
es que removeListener()
devolverá una referencia al EventTarget
.