Eventos
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
Código-fonte: lib/events.js
Grande parte da API principal do Node.js é construída em torno de uma arquitetura assíncrona orientada a eventos idiomática, na qual certos tipos de objetos (chamados de "emissores") emitem eventos nomeados que fazem com que objetos Function
("ouvintes") sejam chamados.
Por exemplo: um objeto net.Server
emite um evento cada vez que um par se conecta a ele; um fs.ReadStream
emite um evento quando o arquivo é aberto; um stream emite um evento sempre que dados estão disponíveis para leitura.
Todos os objetos que emitem eventos são instâncias da classe EventEmitter
. Esses objetos expõem uma função eventEmitter.on()
que permite que uma ou mais funções sejam anexadas a eventos nomeados emitidos pelo objeto. Normalmente, os nomes de eventos são strings em camel-case, mas qualquer chave de propriedade JavaScript válida pode ser usada.
Quando o objeto EventEmitter
emite um evento, todas as funções anexadas a esse evento específico são chamadas sincronamente. Quaisquer valores retornados pelos ouvintes chamados são ignorados e descartados.
O exemplo a seguir mostra uma instância EventEmitter
simples com um único ouvinte. O método eventEmitter.on()
é usado para registrar ouvintes, enquanto o método eventEmitter.emit()
é usado para acionar o evento.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('um evento ocorreu!')
})
myEmitter.emit('event')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('um evento ocorreu!')
})
myEmitter.emit('event')
Passando argumentos e this
para os ouvintes
O método eventEmitter.emit()
permite que um conjunto arbitrário de argumentos seja passado para as funções de ouvinte. Tenha em mente que quando uma função de ouvinte comum é chamada, a palavra-chave padrão this
é intencionalmente definida para referenciar a instância EventEmitter
à qual o ouvinte está anexado.
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')
É possível usar Funções de Seta ES6 como ouvintes, no entanto, ao fazer isso, a palavra-chave this
não referenciará mais a instância 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')
Assíncrono vs. síncrono
O EventEmitter
chama todos os listeners de forma síncrona na ordem em que foram registrados. Isso garante o sequenciamento adequado dos eventos e ajuda a evitar condições de corrida e erros lógicos. Quando apropriado, as funções listener podem alternar para um modo de operação assíncrono usando os métodos setImmediate()
ou process.nextTick()
:
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('isso acontece de forma assíncrona')
})
})
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('isso acontece de forma assíncrona')
})
})
myEmitter.emit('event', 'a', 'b')
Lidando com eventos apenas uma vez
Quando um listener é registrado usando o método eventEmitter.on()
, esse listener é invocado toda vez que o evento nomeado é emitido.
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 o método eventEmitter.once()
, é possível registrar um listener que é chamado no máximo uma vez para um evento específico. Uma vez que o evento é emitido, o listener é desregistrado e então chamado.
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 erro
Quando ocorre um erro dentro de uma instância EventEmitter
, a ação típica é que um evento 'error'
seja emitido. Esses são tratados como casos especiais dentro do Node.js.
Se um EventEmitter
não tiver pelo menos um ouvinte registrado para o evento 'error'
, e um evento 'error'
for emitido, o erro será lançado, um stack trace será impresso e o processo do Node.js será encerrado.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// Lança e quebra o Node.js
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// Lança e quebra o Node.js
Para se proteger contra a quebra do processo do Node.js, o módulo domain
pode ser usado. (Observe, no entanto, que o módulo node:domain
está obsoleto.)
Como uma prática recomendada, os ouvintes devem sempre ser adicionados para os eventos 'error'
.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
console.error('whoops! there was an error')
})
myEmitter.emit('error', new Error('whoops!'))
// Imprime: whoops! there was an error
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
console.error('whoops! there was an error')
})
myEmitter.emit('error', new Error('whoops!'))
// Imprime: whoops! there was an error
É possível monitorar eventos 'error'
sem consumir o erro emitido, instalando um ouvinte usando o 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('whoops!'))
// Ainda lança e quebra o Node.js
const { EventEmitter, errorMonitor } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('whoops!'))
// Ainda lança e quebra o Node.js
Capturar rejeições de Promises
Usar funções async
com manipuladores de eventos é problemático, pois pode levar a uma rejeição não tratada em caso de uma exceção lançada:
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')
})
A opção captureRejections
no construtor EventEmitter
ou a configuração global alteram esse comportamento, instalando um manipulador .then(undefined, handler)
na Promise
. Esse manipulador encaminha a exceção assincronamente para o método Symbol.for('nodejs.rejection')
se houver um, ou para o manipulador de eventos 'error'
se não houver nenhum.
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
Definir events.captureRejections = true
mudará o padrão para todas as novas instâncias 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)
Os eventos 'error'
que são gerados pelo comportamento captureRejections
não têm um manipulador de captura para evitar loops de erro infinitos: a recomendação é não usar funções async
como manipuladores de eventos 'error'
.
Classe: EventEmitter
[Histórico]
Versão | Mudanças |
---|---|
v13.4.0, v12.16.0 | Adicionada a opção captureRejections. |
v0.1.26 | Adicionada em: v0.1.26 |
A classe EventEmitter
é definida e exposta pelo módulo node:events
:
import { EventEmitter } from 'node:events'
const EventEmitter = require('node:events')
Todos os EventEmitter
s emitem o evento 'newListener'
quando novos listeners são adicionados e 'removeListener'
quando listeners existentes são removidos.
Ele suporta a seguinte opção:
captureRejections
<boolean> Habilita a captura automática de rejeição de promise. Padrão:false
.
Evento: 'newListener'
Adicionado em: v0.1.26
eventName
<string> | <symbol> O nome do evento que está sendo escutadolistener
<Function> A função de tratamento do evento
A instância EventEmitter
emitirá seu próprio evento 'newListener'
antes que um listener seja adicionado ao seu array interno de listeners.
Listeners registrados para o evento 'newListener'
recebem o nome do evento e uma referência ao listener que está sendo adicionado.
O fato de que o evento é disparado antes de adicionar o listener tem um efeito colateral sutil, mas importante: quaisquer listeners adicionais registrados com o mesmo nome
dentro do callback de 'newListener'
são inseridos antes do listener que está no processo de ser adicionado.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
// Faça isso apenas uma vez para não criar um loop infinito
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Insere um novo listener na 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()
// Faça isso apenas uma vez para não criar um loop infinito
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Insere um novo listener na frente
myEmitter.on('event', () => {
console.log('B')
})
}
})
myEmitter.on('event', () => {
console.log('A')
})
myEmitter.emit('event')
// Imprime:
// B
// A
Evento: 'removeListener'
[Histórico]
Versão | Mudanças |
---|---|
v6.1.0, v4.7.0 | Para ouvintes anexados usando .once() , o argumento listener agora produz a função ouvinte original. |
v0.9.3 | Adicionado em: v0.9.3 |
eventName
<string> | <symbol> O nome do eventolistener
<Function> A função manipuladora de eventos
O evento 'removeListener'
é emitido depois que o listener
é removido.
emitter.addListener(eventName, listener)
Adicionado em: v0.1.26
eventName
<string> | <symbol>listener
<Function>
Alias para emitter.on(eventName, listener)
.
emitter.emit(eventName[, ...args])
Adicionado em: v0.1.26
Chama síncronamente cada um dos ouvintes registrados para o evento chamado eventName
, na ordem em que foram registrados, passando os argumentos fornecidos para cada um.
Retorna true
se o evento tinha ouvintes, false
caso contrário.
import { EventEmitter } from 'node:events'
const myEmitter = new EventEmitter()
// Primeiro ouvinte
myEmitter.on('event', function firstListener() {
console.log('Olá! primeiro ouvinte')
})
// Segundo ouvinte
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`evento com parâmetros ${arg1}, ${arg2} no segundo ouvinte`)
})
// Terceiro ouvinte
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ')
console.log(`evento com parâmetros ${parameters} no terceiro ouvinte`)
})
console.log(myEmitter.listeners('event'))
myEmitter.emit('event', 1, 2, 3, 4, 5)
// Imprime:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Olá! primeiro ouvinte
// evento com parâmetros 1, 2 no segundo ouvinte
// evento com parâmetros 1, 2, 3, 4, 5 no terceiro ouvinte
const EventEmitter = require('node:events')
const myEmitter = new EventEmitter()
// Primeiro ouvinte
myEmitter.on('event', function firstListener() {
console.log('Olá! primeiro ouvinte')
})
// Segundo ouvinte
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`evento com parâmetros ${arg1}, ${arg2} no segundo ouvinte`)
})
// Terceiro ouvinte
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ')
console.log(`evento com parâmetros ${parameters} no terceiro ouvinte`)
})
console.log(myEmitter.listeners('event'))
myEmitter.emit('event', 1, 2, 3, 4, 5)
// Imprime:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Olá! primeiro ouvinte
// evento com parâmetros 1, 2 no segundo ouvinte
// evento com parâmetros 1, 2, 3, 4, 5 no terceiro ouvinte
emitter.eventNames()
Adicionado em: v6.0.0
- Retorna: <Array>
Retorna um array listando os eventos para os quais o emissor registrou listeners. Os valores no array são strings ou 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()
Adicionado em: v1.0.0
- Retorna: <integer>
Retorna o valor máximo atual do listener para o EventEmitter
, que é definido por emitter.setMaxListeners(n)
ou o padrão é events.defaultMaxListeners
.
emitter.listenerCount(eventName[, listener])
[Histórico]
Versão | Alterações |
---|---|
v19.8.0, v18.16.0 | Adicionado o argumento listener . |
v3.2.0 | Adicionado em: v3.2.0 |
eventName
<string> | <symbol> O nome do evento que está sendo escutadolistener
<Function> A função de manipulação de eventos- Retorna: <integer>
Retorna o número de listeners escutando o evento nomeado eventName
. Se listener
for fornecido, retornará quantas vezes o listener é encontrado na lista de listeners do evento.
emitter.listeners(eventName)
[Histórico]
Versão | Mudanças |
---|---|
v7.0.0 | Para os listeners anexados usando .once() , isso agora retorna os listeners originais em vez de funções wrapper. |
v0.1.26 | Adicionado em: v0.1.26 |
eventName
<string> | <symbol>- Retorna: <Function[]>
Retorna uma cópia do array de listeners para o evento nomeado eventName
.
server.on('connection', stream => {
console.log('alguém conectou!')
})
console.log(util.inspect(server.listeners('connection')))
// Imprime: [ [Function] ]
emitter.off(eventName, listener)
Adicionado em: v10.0.0
eventName
<string> | <symbol>listener
<Function>- Retorna: <EventEmitter>
Alias para emitter.removeListener()
.
emitter.on(eventName, listener)
Adicionado em: v0.1.101
eventName
<string> | <symbol> O nome do evento.listener
<Function> A função de callback- Retorna: <EventEmitter>
Adiciona a função listener
ao final do array de listeners para o evento nomeado eventName
. Não são feitas verificações para ver se o listener
já foi adicionado. Várias chamadas passando a mesma combinação de eventName
e listener
resultarão no listener
sendo adicionado e chamado várias vezes.
server.on('connection', stream => {
console.log('alguém conectou!')
})
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
Por padrão, os listeners de eventos são invocados na ordem em que são adicionados. O método emitter.prependListener()
pode ser usado como alternativa para adicionar o listener de evento ao início do 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)
Adicionado em: v0.3.0
eventName
<string> | <symbol> O nome do evento.listener
<Function> A função de callback- Retorna: <EventEmitter>
Adiciona uma função listener
única para o evento nomeado eventName
. Na próxima vez que eventName
for acionado, este listener será removido e então invocado.
server.once('connection', stream => {
console.log('Ah, temos nosso primeiro usuário!')
})
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
Por padrão, os listeners de eventos são invocados na ordem em que são adicionados. O método emitter.prependOnceListener()
pode ser usado como uma alternativa para adicionar o listener de eventos ao início do 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)
Adicionado em: v6.0.0
eventName
<string> | <symbol> O nome do evento.listener
<Function> A função de callback- Retorna: <EventEmitter>
Adiciona a função listener
ao início do array de listeners para o evento nomeado eventName
. Nenhuma verificação é feita para ver se o listener
já foi adicionado. Múltiplas chamadas passando a mesma combinação de eventName
e listener
resultarão no listener
sendo adicionado e chamado várias vezes.
server.prependListener('connection', stream => {
console.log('alguém se conectou!')
})
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
emitter.prependOnceListener(eventName, listener)
Adicionado em: v6.0.0
eventName
<string> | <symbol> O nome do evento.listener
<Function> A função de callback- Retorna: <EventEmitter>
Adiciona uma função listener
única para o evento chamado eventName
ao início do array de listeners. Na próxima vez que eventName
for acionado, este listener é removido e, em seguida, invocado.
server.prependOnceListener('connection', stream => {
console.log('Ah, temos nosso primeiro usuário!')
})
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
emitter.removeAllListeners([eventName])
Adicionado em: v0.1.26
eventName
<string> | <symbol>- Retorna: <EventEmitter>
Remove todos os listeners, ou aqueles do eventName
especificado.
É uma má prática remover listeners adicionados em outro lugar no código, particularmente quando a instância EventEmitter
foi criada por algum outro componente ou módulo (por exemplo, sockets ou fluxos de arquivos).
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
emitter.removeListener(eventName, listener)
Adicionado em: v0.1.26
eventName
<string> | <symbol>listener
<Function>- Retorna: <EventEmitter>
Remove o listener
especificado do array de listeners para o evento chamado eventName
.
const callback = stream => {
console.log('alguém se conectou!')
}
server.on('connection', callback)
// ...
server.removeListener('connection', callback)
removeListener()
removerá, no máximo, uma instância de um listener do array de listeners. Se qualquer listener único tiver sido adicionado várias vezes ao array de listeners para o eventName
especificado, então removeListener()
deve ser chamado várias vezes para remover cada instância.
Uma vez que um evento é emitido, todos os listeners anexados a ele no momento da emissão são chamados em ordem. Isso implica que qualquer chamada de removeListener()
ou removeAllListeners()
depois da emissão e antes que o último listener termine a execução não os removerá de emit()
em andamento. Os eventos subsequentes se comportam como esperado.
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 remove o listener callbackB, mas ele ainda será chamado.
// Array interno de listeners no momento da emissão [callbackA, callbackB]
myEmitter.emit('event')
// Imprime:
// A
// B
// callbackB agora está removido.
// Array 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 remove o listener callbackB, mas ele ainda será chamado.
// Array interno de listeners no momento da emissão [callbackA, callbackB]
myEmitter.emit('event')
// Imprime:
// A
// B
// callbackB agora está removido.
// Array interno de listeners [callbackA]
myEmitter.emit('event')
// Imprime:
// A
Como os listeners são gerenciados usando um array interno, chamar isso alterará os índices de posição de qualquer listener registrado depois do listener que está sendo removido. Isso não afetará a ordem em que os listeners são chamados, mas significa que quaisquer cópias do array de listeners retornadas pelo método emitter.listeners()
precisarão ser recriadas.
Quando uma única função foi adicionada como um manipulador várias vezes para um único evento (como no exemplo abaixo), removeListener()
removerá a instância adicionada mais recentemente. No exemplo, o listener once('ping')
é removido:
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')
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
emitter.setMaxListeners(n)
Adicionado em: v0.3.5
n
<integer>- Retorna: <EventEmitter>
Por padrão, os EventEmitter
s imprimirão um aviso se mais de 10
listeners forem adicionados para um evento específico. Este é um padrão útil que ajuda a encontrar vazamentos de memória. O método emitter.setMaxListeners()
permite que o limite seja modificado para esta instância específica de EventEmitter
. O valor pode ser definido como Infinity
(ou 0
) para indicar um número ilimitado de listeners.
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
emitter.rawListeners(eventName)
Adicionado em: v9.4.0
eventName
<string> | <symbol>- Retorna: <Function[]>
Retorna uma cópia do array de listeners para o evento nomeado eventName
, incluindo quaisquer wrappers (como aqueles criados por .once()
).
import { EventEmitter } from 'node:events'
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// Retorna um novo Array com uma função `onceWrapper` que possui uma propriedade
// `listener` que contém o listener original vinculado acima
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// Imprime "log once" no console e não desvincula o evento `once`
logFnWrapper.listener()
// Imprime "log once" no console e remove o listener
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// Retornará um novo Array com uma única função vinculada por `.on()` acima
const newListeners = emitter.rawListeners('log')
// Imprime "log persistently" duas vezes
newListeners[0]()
emitter.emit('log')
const EventEmitter = require('node:events')
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// Retorna um novo Array com uma função `onceWrapper` que possui uma propriedade
// `listener` que contém o listener original vinculado acima
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// Imprime "log once" no console e não desvincula o evento `once`
logFnWrapper.listener()
// Imprime "log once" no console e remove o listener
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// Retornará um novo Array com uma única função vinculada por `.on()` acima
const newListeners = emitter.rawListeners('log')
// Imprime "log persistently" duas vezes
newListeners[0]()
emitter.emit('log')
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
[Histórico]
Versão | Mudanças |
---|---|
v17.4.0, v16.14.0 | Não é mais experimental. |
v13.4.0, v12.16.0 | Adicionado em: v13.4.0, v12.16.0 |
O método Symbol.for('nodejs.rejection')
é chamado caso ocorra uma rejeição de promessa ao emitir um evento e captureRejections
estiver habilitado no emissor. É possível usar events.captureRejectionSymbol
no 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('rejeição ocorreu para', event, 'com', err, ...args)
this.destroy(err)
}
destroy(err) {
// Destrua o recurso aqui.
}
}
const { EventEmitter, captureRejectionSymbol } = require('node:events')
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true })
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejeição ocorreu para', event, 'com', err, ...args)
this.destroy(err)
}
destroy(err) {
// Destrua o recurso aqui.
}
}
events.defaultMaxListeners
Adicionado em: v0.11.2
Por padrão, um máximo de 10
ouvintes podem ser registrados para qualquer evento individual. Este limite pode ser alterado para instâncias individuais de EventEmitter
usando o método emitter.setMaxListeners(n)
. Para alterar o padrão para todas as instâncias de EventEmitter
, a propriedade events.defaultMaxListeners
pode ser usada. Se esse valor não for um número positivo, um RangeError
será lançado.
Tome cuidado ao definir events.defaultMaxListeners
, pois a alteração afeta todas as instâncias de EventEmitter
, incluindo aquelas criadas antes da alteração ser feita. No entanto, chamar emitter.setMaxListeners(n)
ainda tem precedência sobre events.defaultMaxListeners
.
Este não é um limite rígido. A instância de EventEmitter
permitirá que mais ouvintes sejam adicionados, mas produzirá um aviso de rastreamento para stderr indicando que um "possível vazamento de memória de EventEmitter" foi detectado. Para qualquer EventEmitter
individual, os métodos emitter.getMaxListeners()
e emitter.setMaxListeners()
podem ser usados para evitar temporariamente este aviso:
defaultMaxListeners
não tem efeito nas instâncias de AbortSignal
. Embora ainda seja possível usar emitter.setMaxListeners(n)
para definir um limite de aviso para instâncias individuais de AbortSignal
, por padrão as instâncias de AbortSignal
não avisarão.
import { EventEmitter } from 'node:events'
const emitter = new EventEmitter()
emitter.setMaxListeners(emitter.getMaxListeners() + 1)
emitter.once('event', () => {
// faça algo
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', () => {
// faça algo
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0))
})
A flag de linha de comando --trace-warnings
pode ser usada para exibir o rastreamento de pilha para tais avisos.
O aviso emitido pode ser inspecionado com process.on('warning')
e terá as propriedades adicionais emitter
, type
e count
, referindo-se à instância do emissor de eventos, ao nome do evento e ao número de ouvintes anexados, respectivamente. Sua propriedade name
é definida como 'MaxListenersExceededWarning'
.
events.errorMonitor
Adicionado em: v13.6.0, v12.17.0
Este símbolo deve ser usado para instalar um ouvinte apenas para monitorar eventos 'error'
. Os ouvintes instalados usando este símbolo são chamados antes que os ouvintes regulares 'error'
sejam chamados.
Instalar um ouvinte usando este símbolo não altera o comportamento quando um evento 'error'
é emitido. Portanto, o processo ainda irá falhar se nenhum ouvinte regular 'error'
estiver instalado.
events.getEventListeners(emitterOrTarget, eventName)
Adicionado em: v15.2.0, v14.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>eventName
<string> | <symbol>- Retorna: <Function[]>
Retorna uma cópia do array de ouvintes para o evento chamado eventName
.
Para EventEmitter
s, isso se comporta exatamente da mesma forma que chamar .listeners
no emissor.
Para EventTarget
s, esta é a única maneira de obter os ouvintes de eventos para o destino do evento. Isso é útil para fins de depuração e diagnóstico.
import { getEventListeners, EventEmitter } from 'node:events'
{
const ee = new EventEmitter()
const listener = () => console.log('Eventos são divertidos')
ee.on('foo', listener)
console.log(getEventListeners(ee, 'foo')) // [ [Function: listener] ]
}
{
const et = new EventTarget()
const listener = () => console.log('Eventos são divertidos')
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('Eventos são divertidos')
ee.on('foo', listener)
console.log(getEventListeners(ee, 'foo')) // [ [Function: listener] ]
}
{
const et = new EventTarget()
const listener = () => console.log('Eventos são divertidos')
et.addEventListener('foo', listener)
console.log(getEventListeners(et, 'foo')) // [ [Function: listener] ]
}
events.getMaxListeners(emitterOrTarget)
Adicionado em: v19.9.0, v18.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>- Retorna: <number>
Retorna a quantidade máxima de listeners atualmente definida.
Para EventEmitter
s, isso se comporta exatamente da mesma forma que chamar .getMaxListeners
no emissor.
Para EventTarget
s, esta é a única maneira de obter o número máximo de listeners de eventos para o destino do evento. Se o número de manipuladores de eventos em um único EventTarget exceder o máximo definido, o EventTarget imprimirá um aviso.
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(emitter, name[, options])
[Histórico]
Versão | Mudanças |
---|---|
v15.0.0 | A opção signal agora é suportada. |
v11.13.0, v10.16.0 | Adicionado em: v11.13.0, v10.16.0 |
emitter
<EventEmitter>name
<string> | <symbol>options
<Object>signal
<AbortSignal> Pode ser usado para cancelar a espera pelo evento.
- Retorna: <Promise>
Cria uma Promise
que é cumprida quando o EventEmitter
emite o evento fornecido ou que é rejeitada se o EventEmitter
emitir 'error'
durante a espera. A Promise
será resolvida com um array de todos os argumentos emitidos para o evento fornecido.
Este método é intencionalmente genérico e funciona com a interface da plataforma web EventTarget, que não tem semântica de evento especial 'error'
e não ouve o 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()
O tratamento especial do evento 'error'
é usado apenas quando events.once()
é usado para esperar por outro evento. Se events.once()
for usado para esperar pelo próprio evento 'error'
, ele será tratado como qualquer outro tipo de evento, sem tratamento 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
Um <AbortSignal> pode ser usado para cancelar a espera pelo 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!
Aguardando múltiplos eventos emitidos em process.nextTick()
Existe um caso extremo que vale a pena notar ao usar a função events.once()
para aguardar múltiplos eventos emitidos no mesmo lote de operações process.nextTick()
, ou sempre que múltiplos eventos são emitidos de forma síncrona. Especificamente, porque a fila process.nextTick()
é drenada antes da fila de microtarefas Promise
, e porque EventEmitter
emite todos os eventos de forma síncrona, é possível que events.once()
perca um 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 será resolvida porque o evento 'foo' já terá
// sido emitido antes da Promise ser criada.
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 será resolvida porque o evento 'foo' já terá
// sido emitido antes da Promise ser criada.
await once(myEE, 'foo')
console.log('foo')
}
process.nextTick(() => {
myEE.emit('bar')
myEE.emit('foo')
})
foo().then(() => console.log('done'))
Para capturar ambos os eventos, crie cada uma das Promises antes de aguardar qualquer uma delas, então torna-se possível usar Promise.all()
, Promise.race()
, ou 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
[Histórico]
Versão | Mudanças |
---|---|
v17.4.0, v16.14.0 | Não é mais experimental. |
v13.4.0, v12.16.0 | Adicionado em: v13.4.0, v12.16.0 |
Valor: <boolean>
Altere a opção padrão captureRejections
em todos os novos objetos EventEmitter
.
events.captureRejectionSymbol
[Histórico]
Versão | Mudanças |
---|---|
v17.4.0, v16.14.0 | Não é mais experimental. |
v13.4.0, v12.16.0 | Adicionado em: v13.4.0, v12.16.0 |
Valor: Symbol.for('nodejs.rejection')
Veja como escrever um manipulador de rejeição personalizado.
events.listenerCount(emitter, eventName)
Adicionado em: v0.9.12
Obsoleto desde: v3.2.0
[Estável: 0 - Obsoleto]
Estável: 0 Estabilidade: 0 - Obsoleto: Use emitter.listenerCount()
em vez disso.
emitter
<EventEmitter> O emissor a ser consultadoeventName
<string> | <symbol> O nome do evento
Um método de classe que retorna o número de listeners para o eventName
fornecido, registrados no emitter
fornecido.
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(emitter, eventName[, options])
[Histórico]
Versão | Mudanças |
---|---|
v22.0.0, v20.13.0 | Suporte para opções highWaterMark e lowWaterMark , para consistência. As opções antigas ainda são suportadas. |
v20.0.0 | As opções close , highWatermark e lowWatermark são suportadas agora. |
v13.6.0, v12.16.0 | Adicionado em: v13.6.0, v12.16.0 |
emitter
<EventEmitter>eventName
<string> | <symbol> O nome do evento que está sendo escutadooptions
<Object>signal
<AbortSignal> Pode ser usado para cancelar eventos aguardando.close
- <string[]> Nomes de eventos que finalizarão a iteração.highWaterMark
- <integer> Padrão:Number.MAX_SAFE_INTEGER
O limite máximo. O emissor é pausado sempre que o tamanho dos eventos sendo armazenados em buffer é maior do que ele. Suportado apenas em emissores que implementam os métodospause()
eresume()
.lowWaterMark
- <integer> Padrão:1
O limite mínimo. O emissor é retomado sempre que o tamanho dos eventos sendo armazenados em buffer é menor do que ele. Suportado apenas em emissores que implementam os métodospause()
eresume()
.
Retorna: <AsyncIterator> que itera eventos
eventName
emitidos peloemitter
import { on, EventEmitter } from 'node:events'
import process from 'node:process'
const ee = new EventEmitter()
// Emitir mais tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo')) {
// A execução deste bloco interno é síncrona e ele
// processa um evento por vez (mesmo com await). Não use
// se a execução simultânea for necessária.
console.log(event) // imprime ['bar'] [42]
}
// Inatingível aqui
const { on, EventEmitter } = require('node:events')
;(async () => {
const ee = new EventEmitter()
// Emitir mais tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo')) {
// A execução deste bloco interno é síncrona e ele
// processa um evento por vez (mesmo com await). Não use
// se a execução simultânea for necessária.
console.log(event) // imprime ['bar'] [42]
}
// Inatingível aqui
})()
Retorna um AsyncIterator
que itera eventos eventName
. Ele lançará um erro se o EventEmitter
emitir 'error'
. Ele remove todos os listeners ao sair do loop. O valor
retornado por cada iteração é um array composto pelos argumentos de evento emitidos.
Um <AbortSignal> pode ser usado para cancelar a espera por eventos:
import { on, EventEmitter } from 'node:events'
import process from 'node:process'
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// Emitir mais tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// A execução deste bloco interno é síncrona e ele
// processa um evento por vez (mesmo com await). Não use
// se a execução simultânea for necessária.
console.log(event) // imprime ['bar'] [42]
}
// Inatingível aqui
})()
process.nextTick(() => ac.abort())
const { on, EventEmitter } = require('node:events')
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// Emitir mais tarde
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// A execução deste bloco interno é síncrona e ele
// processa um evento por vez (mesmo com await). Não use
// se a execução simultânea for necessária.
console.log(event) // imprime ['bar'] [42]
}
// Inatingível aqui
})()
process.nextTick(() => ac.abort())
events.setMaxListeners(n[, ...eventTargets])
Adicionado em: v15.4.0
n
<number> Um número não negativo. O número máximo de listeners por eventoEventTarget
....eventsTargets
<EventTarget[]> | <EventEmitter[]> Zero ou mais instâncias de <EventTarget> ou <EventEmitter>. Se nenhum for especificado,n
é definido como o máximo padrão para todos os objetos <EventTarget> e <EventEmitter> recém-criados.
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)
Adicionado em: v20.5.0, v18.18.0
[Estável: 1 - Experimental]
Estável: 1 Estabilidade: 1 - Experimental
signal
<AbortSignal>listener
<Function> | <EventListener>- Retorna: <Disposable> Um Disposable que remove o listener de
abort
.
Ouve uma vez o evento abort
no signal
fornecido.
Ouvir o evento abort
em sinais de aborto é inseguro e pode levar a vazamentos de recursos, pois terceiros com o sinal podem chamar e.stopImmediatePropagation()
. Infelizmente, o Node.js não pode mudar isso, pois violaria o padrão da web. Além disso, a API original torna fácil esquecer de remover os listeners.
Essa API permite usar AbortSignal
s com segurança nas APIs do Node.js, resolvendo esses dois problemas, ouvindo o evento de forma que stopImmediatePropagation
não impeça que o listener seja executado.
Retorna um disposable para que possa ser desinscrito mais facilmente.
const { addAbortListener } = require('node:events')
function example(signal) {
let disposable
try {
signal.addEventListener('abort', e => e.stopImmediatePropagation())
disposable = addAbortListener(signal, e => {
// Faça algo quando o sinal for abortado.
})
} 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 => {
// Faça algo quando o sinal for abortado.
})
} finally {
disposable?.[Symbol.dispose]()
}
}
Classe: events.EventEmitterAsyncResource extends EventEmitter
Adicionado em: v17.4.0, v16.14.0
Integra EventEmitter
com <AsyncResource> para EventEmitter
s que exigem rastreamento assíncrono manual. Especificamente, todos os eventos emitidos por instâncias de events.EventEmitterAsyncResource
serão executados dentro de seu contexto assíncrono.
import { EventEmitterAsyncResource, EventEmitter } from 'node:events'
import { notStrictEqual, strictEqual } from 'node:assert'
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks'
// As ferramentas de rastreamento assíncrono identificarão isso como 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' })
// Os ouvintes 'foo' serão executados no contexto assíncrono do EventEmitter.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// Os ouvintes 'foo' em EventEmitters comuns que não rastreiam o contexto
// assíncrono, no entanto, são executados no mesmo contexto assíncrono que o 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')
// As ferramentas de rastreamento assíncrono identificarão isso como 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' })
// Os ouvintes 'foo' serão executados no contexto assíncrono do EventEmitter.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// Os ouvintes 'foo' em EventEmitters comuns que não rastreiam o contexto
// assíncrono, no entanto, são executados no mesmo contexto assíncrono que o emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId)
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId)
})
Promise.resolve().then(() => {
ee1.emit('foo')
ee2.emit('foo')
})
A classe EventEmitterAsyncResource
possui os mesmos métodos e aceita as mesmas opções que EventEmitter
e AsyncResource
eles mesmos.
new events.EventEmitterAsyncResource([options])
options
<Objeto>captureRejections
<boolean> Habilita a captura automática de rejeição de promessas. Padrão:false
.name
<string> O tipo de evento assíncrono. Padrão:new.target.name
.triggerAsyncId
<number> O ID do contexto de execução que criou este evento assíncrono. Padrão:executionAsyncId()
.requireManualDestroy
<boolean> Se definido comotrue
, desabilitaemitDestroy
quando o objeto é coletado pelo coletor de lixo. Normalmente não é necessário definir isso (mesmo seemitDestroy
for chamado manualmente), a menos que oasyncId
do recurso seja recuperado e a API sensívelemitDestroy
seja chamada com ele. Quando definido comofalse
, a chamadaemitDestroy
na coleta de lixo só ocorrerá se houver pelo menos um ganchodestroy
ativo. Padrão:false
.
eventemitterasyncresource.asyncId
- Tipo: <number> O
asyncId
exclusivo atribuído ao recurso.
eventemitterasyncresource.asyncResource
- Tipo: O <AsyncResource> subjacente.
O objeto AsyncResource
retornado tem uma propriedade adicional eventEmitter
que fornece uma referência a este EventEmitterAsyncResource
.
eventemitterasyncresource.emitDestroy()
Chama todos os ganchos destroy
. Isso só deve ser chamado uma vez. Um erro será lançado se for chamado mais de uma vez. Isso deve ser chamado manualmente. Se o recurso for deixado para ser coletado pelo GC, os ganchos destroy
nunca serão chamados.
eventemitterasyncresource.triggerAsyncId
- Tipo: <number> O mesmo
triggerAsyncId
que é passado para o construtorAsyncResource
.
API EventTarget
e Event
[Histórico]
Versão | Mudanças |
---|---|
v16.0.0 | Mudança no tratamento de erros do EventTarget. |
v15.4.0 | Não é mais experimental. |
v15.0.0 | As classes EventTarget e Event agora estão disponíveis como globais. |
v14.5.0 | Adicionado em: v14.5.0 |
Os objetos EventTarget
e Event
são uma implementação específica do Node.js da EventTarget
Web API que são expostos por algumas APIs principais do Node.js.
const target = new EventTarget()
target.addEventListener('foo', event => {
console.log('evento foo aconteceu!')
})
EventTarget
do Node.js vs. EventTarget
do DOM
Existem duas diferenças principais entre o EventTarget
do Node.js e a EventTarget
Web API:
NodeEventTarget
vs. EventEmitter
O objeto NodeEventTarget
implementa um subconjunto modificado da API EventEmitter
que permite que ele emule de perto um EventEmitter
em certas situações. Um NodeEventTarget
não é uma instância de EventEmitter
e não pode ser usado no lugar de um EventEmitter
na maioria dos casos.
Ouvinte de evento
Ouvintes de eventos registrados para um evento type
podem ser funções JavaScript ou objetos com uma propriedade handleEvent
cujo valor é uma função.
Em ambos os casos, a função de tratamento é invocada com o argumento event
passado para a função eventTarget.dispatchEvent()
.
Funções assíncronas podem ser usadas como ouvintes de eventos. Se uma função de tratamento assíncrona for rejeitada, a rejeição é capturada e tratada conforme descrito em tratamento de erros do EventTarget
.
Um erro lançado por uma função de tratamento não impede que os outros tratadores sejam invocados.
O valor de retorno de uma função de tratamento é ignorado.
Os tratadores são sempre invocados na ordem em que foram adicionados.
As funções de tratamento podem mutar o 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 })
Tratamento de erros do EventTarget
Quando um listener de evento registrado lança (ou retorna uma Promise que é rejeitada), por padrão, o erro é tratado como uma exceção não capturada em process.nextTick()
. Isso significa que exceções não capturadas em EventTarget
s encerrarão o processo do Node.js por padrão.
Lançar dentro de um listener de evento não impedirá que outros handlers registrados sejam invocados.
O EventTarget
não implementa nenhum tratamento padrão especial para eventos do tipo 'error'
como o EventEmitter
.
Atualmente, os erros são primeiro encaminhados para o evento process.on('error')
antes de atingir process.on('uncaughtException')
. Este comportamento está obsoleto e será alterado em uma versão futura para alinhar o EventTarget
com outras APIs do Node.js. Qualquer código que dependa do evento process.on('error')
deve ser alinhado com o novo comportamento.
Classe: Event
[Histórico]
Versão | Mudanças |
---|---|
v15.0.0 | A classe Event agora está disponível através do objeto global. |
v14.5.0 | Adicionado em: v14.5.0 |
O objeto Event
é uma adaptação da Event
Web API. As instâncias são criadas internamente pelo Node.js.
event.bubbles
Adicionado em: v14.5.0
- Tipo: <boolean> Sempre retorna
false
.
Isso não é usado no Node.js e é fornecido puramente para fins de completude.
event.cancelBubble
Adicionado em: v14.5.0
[Estável: 3 - Legado]
Estável: 3 Estabilidade: 3 - Legado: Use event.stopPropagation()
em vez disso.
- Tipo: <boolean>
Alias para event.stopPropagation()
se definido como true
. Isso não é usado no Node.js e é fornecido puramente para fins de completude.
event.cancelable
Adicionado em: v14.5.0
- Tipo: <boolean> Verdadeiro se o evento foi criado com a opção
cancelable
.
event.composed
Adicionado em: v14.5.0
- Tipo: <boolean> Sempre retorna
false
.
Isso não é usado no Node.js e é fornecido apenas para fins de integridade.
event.composedPath()
Adicionado em: v14.5.0
Retorna um array contendo o EventTarget
atual como a única entrada ou vazio se o evento não estiver sendo despachado. Isso não é usado no Node.js e é fornecido apenas para fins de integridade.
event.currentTarget
Adicionado em: v14.5.0
- Tipo: <EventTarget> O
EventTarget
que está despachando o evento.
Alias para event.target
.
event.defaultPrevented
Adicionado em: v14.5.0
- Tipo: <boolean>
É true
se cancelable
for true
e event.preventDefault()
tiver sido chamado.
event.eventPhase
Adicionado em: v14.5.0
- Tipo: <number> Retorna
0
enquanto um evento não está sendo despachado,2
enquanto está sendo despachado.
Isso não é usado no Node.js e é fornecido apenas para fins de integridade.
event.initEvent(type[, bubbles[, cancelable]])
Adicionado em: v19.5.0
[Estável: 3 - Legado]
Estável: 3 Estabilidade: 3 - Legado: A especificação WHATWG considera isso obsoleto e os usuários não devem usá-lo de forma alguma.
Redundante com os construtores de eventos e incapaz de definir composed
. Isso não é usado no Node.js e é fornecido apenas para fins de integridade.
event.isTrusted
Adicionado em: v14.5.0
- Tipo: <boolean>
O evento "abort"
de <AbortSignal> é emitido com isTrusted
definido como true
. O valor é false
em todos os outros casos.
event.preventDefault()
Adicionado em: v14.5.0
Define a propriedade defaultPrevented
como true
se cancelable
for true
.
event.returnValue
Adicionado em: v14.5.0
[Estável: 3 - Legado]
Estável: 3 Estabilidade: 3 - Legado: Use event.defaultPrevented
em vez disso.
- Tipo: <boolean> Verdadeiro se o evento não foi cancelado.
O valor de event.returnValue
é sempre o oposto de event.defaultPrevented
. Isto não é usado em Node.js e é fornecido puramente para fins de completude.
event.srcElement
Adicionado em: v14.5.0
[Estável: 3 - Legado]
Estável: 3 Estabilidade: 3 - Legado: Use event.target
em vez disso.
- Tipo: <EventTarget> O
EventTarget
que despacha o evento.
Alias para event.target
.
event.stopImmediatePropagation()
Adicionado em: v14.5.0
Interrompe a invocação de listeners de evento após o término do atual.
event.stopPropagation()
Adicionado em: v14.5.0
Isto não é usado em Node.js e é fornecido puramente para fins de completude.
event.target
Adicionado em: v14.5.0
- Tipo: <EventTarget> O
EventTarget
que despacha o evento.
event.timeStamp
Adicionado em: v14.5.0
- Tipo: <number>
O timestamp em milissegundos quando o objeto Event
foi criado.
event.type
Adicionado em: v14.5.0
- Tipo: <string>
O identificador do tipo de evento.
Classe: EventTarget
[Histórico]
Versão | Alterações |
---|---|
v15.0.0 | A classe EventTarget agora está disponível através do objeto global. |
v14.5.0 | Adicionado em: v14.5.0 |
eventTarget.addEventListener(type, listener[, options])
[Histórico]
Versão | Mudanças |
---|---|
v15.4.0 | adiciona suporte para a opção signal . |
v14.5.0 | Adicionado em: v14.5.0 |
type
<string>listener
<Function> | <EventListener>options
<Object>once
<boolean> Quandotrue
, o listener é removido automaticamente quando é invocado pela primeira vez. Padrão:false
.passive
<boolean> Quandotrue
, serve como uma dica de que o listener não chamará o métodopreventDefault()
do objetoEvent
. Padrão:false
.capture
<boolean> Não usado diretamente pelo Node.js. Adicionado para integridade da API. Padrão:false
.signal
<AbortSignal> O listener será removido quando o métodoabort()
do objeto AbortSignal fornecido for chamado.
Adiciona um novo manipulador para o evento type
. Qualquer listener
fornecido é adicionado apenas uma vez por type
e por valor de opção capture
.
Se a opção once
for true
, o listener
será removido após a próxima vez que um evento type
for disparado.
A opção capture
não é usada pelo Node.js de nenhuma maneira funcional além de rastrear listeners de evento registrados de acordo com a especificação EventTarget
. Especificamente, a opção capture
é usada como parte da chave ao registrar um listener
. Qualquer listener
individual pode ser adicionado uma vez com capture = false
e uma vez com capture = true
.
function handler(event) {}
const target = new EventTarget()
target.addEventListener('foo', handler, { capture: true }) // primeiro
target.addEventListener('foo', handler, { capture: false }) // segundo
// Remove a segunda instância do handler
target.removeEventListener('foo', handler)
// Remove a primeira instância do handler
target.removeEventListener('foo', handler, { capture: true })
eventTarget.dispatchEvent(event)
Adicionado em: v14.5.0
event
<Event>- Retorna: <boolean>
true
se o valor do atributocancelable
do evento for falso ou seu métodopreventDefault()
não foi invocado, caso contrário,false
.
Dispara o event
para a lista de manipuladores para event.type
.
Os listeners de evento registrados são invocados de forma síncrona na ordem em que foram registrados.
eventTarget.removeEventListener(type, listener[, options])
Adicionado em: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Remove o listener
da lista de manipuladores para o evento type
.
Classe: CustomEvent
[Histórico]
Versão | Mudanças |
---|---|
v23.0.0 | Não é mais experimental. |
v22.1.0, v20.13.0 | CustomEvent agora é estável. |
v19.0.0 | Não está mais atrás da flag CLI --experimental-global-customevent . |
v18.7.0, v16.17.0 | Adicionado em: v18.7.0, v16.17.0 |
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
- Estende: <Event>
O objeto CustomEvent
é uma adaptação da CustomEvent
Web API. As instâncias são criadas internamente pelo Node.js.
event.detail
[Histórico]
Versão | Mudanças |
---|---|
v22.1.0, v20.13.0 | CustomEvent agora é estável. |
v18.7.0, v16.17.0 | Adicionado em: v18.7.0, v16.17.0 |
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
- Tipo: <any> Retorna os dados personalizados passados ao inicializar.
Somente leitura.
Classe: NodeEventTarget
Adicionado em: v14.5.0
- Extende: <EventTarget>
O NodeEventTarget
é uma extensão específica do Node.js para EventTarget
que emula um subconjunto da API EventEmitter
.
nodeEventTarget.addListener(type, listener)
Adicionado em: v14.5.0
type
<string>listener
<Function> | <EventListener>- Retorna: <EventTarget> this
Extensão específica do Node.js para a classe EventTarget
que emula a API EventEmitter
equivalente. A única diferença entre addListener()
e addEventListener()
é que addListener()
retornará uma referência para o EventTarget
.
nodeEventTarget.emit(type, arg)
Adicionado em: v15.2.0
type
<string>arg
<any>- Retorna: <boolean>
true
se ouvintes de eventos registrados para otype
existirem, caso contrário,false
.
Extensão específica do Node.js para a classe EventTarget
que despacha o arg
para a lista de manipuladores para type
.
nodeEventTarget.eventNames()
Adicionado em: v14.5.0
- Retorna: <string[]>
Extensão específica do Node.js para a classe EventTarget
que retorna um array de nomes type
de eventos para os quais os ouvintes de eventos estão registrados.
nodeEventTarget.listenerCount(type)
Adicionado em: v14.5.0
Extensão específica do Node.js para a classe EventTarget
que retorna o número de ouvintes de eventos registrados para o type
.
nodeEventTarget.setMaxListeners(n)
Adicionado em: v14.5.0
n
<number>
Extensão específica do Node.js para a classe EventTarget
que define o número máximo de listeners de eventos como n
.
nodeEventTarget.getMaxListeners()
Adicionado em: v14.5.0
- Retorna: <number>
Extensão específica do Node.js para a classe EventTarget
que retorna o número máximo de listeners de eventos.
nodeEventTarget.off(type, listener[, options])
Adicionado em: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Retorna: <EventTarget> this
Alias específico do Node.js para eventTarget.removeEventListener()
.
nodeEventTarget.on(type, listener)
Adicionado em: v14.5.0
type
<string>listener
<Function> | <EventListener>- Retorna: <EventTarget> this
Alias específico do Node.js para eventTarget.addEventListener()
.
nodeEventTarget.once(type, listener)
Adicionado em: v14.5.0
type
<string>listener
<Function> | <EventListener>- Retorna: <EventTarget> this
Extensão específica do Node.js para a classe EventTarget
que adiciona um listener once
para o type
de evento fornecido. Isso é equivalente a chamar on
com a opção once
definida como true
.
nodeEventTarget.removeAllListeners([type])
Adicionado em: v14.5.0
type
<string>- Retorna: <EventTarget> this
Extensão específica do Node.js para a classe EventTarget
. Se type
for especificado, remove todos os listeners registrados para type
, caso contrário, remove todos os listeners registrados.
nodeEventTarget.removeListener(type, listener[, options])
Adicionado em: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Retorna: <EventTarget> this
Extensão específica do Node.js para a classe EventTarget
que remove o listener
para o type
fornecido. A única diferença entre removeListener()
e removeEventListener()
é que removeListener()
retornará uma referência ao EventTarget
.