Eventos
[Estável: 2 - Estável]
Estável: 2 Estabilidade: 2 - Estável
Código-fonte: lib/events.js
Grande parte da API central do Node.js é construída em torno de uma arquitetura idiomática assíncrona orientada a eventos, 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 os 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 camelCase, 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 simples de EventEmitter
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 ouvintes
O método eventEmitter.emit()
permite que um conjunto arbitrário de argumentos seja passado para as funções de ouvinte. Lembre-se de 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 fará mais referência à 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 a sequência adequada de eventos e ajuda a evitar condições de corrida e erros de lógica. Quando apropriado, as funções de listener podem mudar 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('this happens asynchronously');
});
});
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('this happens asynchronously');
});
});
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');
// Prints: 1
myEmitter.emit('event');
// Prints: 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');
// Prints: 1
myEmitter.emit('event');
// Prints: 2
Usando o método eventEmitter.once()
, é possível registrar um listener que é chamado no máximo uma vez para um evento específico. Assim que o evento é emitido, o listener é removido do registro 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');
// Prints: 1
myEmitter.emit('event');
// Ignored
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');
// Prints: 1
myEmitter.emit('event');
// Ignored
Eventos de Erro
Quando ocorre um erro dentro de uma instância de EventEmitter
, a ação típica é que um evento 'error'
seja emitido. Estes 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 é lançado, um stack trace é impresso e o processo Node.js é encerrado.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Lança e trava 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 trava o Node.js
Para se proteger contra a falha do processo Node.js, o módulo domain
pode ser usado. (Observe, no entanto, que o módulo node:domain
está obsoleto.)
Como uma melhor prática, 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 trava 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 trava 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
. Este 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.
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 possuem 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ções de promessas. 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 de eventos
A instância EventEmitter
emitirá seu próprio evento 'newListener'
antes que um listener seja adicionado ao seu array interno de listeners.
Os listeners registrados para o evento 'newListener'
recebem o nome do evento e uma referência ao listener que está sendo adicionado.
O fato de o evento ser acionado antes de adicionar o listener tem um efeito colateral sutil, mas importante: quaisquer listeners adicionais registrados com o mesmo name
dentro do callback '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 entrarmos em 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 entrarmos em 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 listeners anexados usando .once() , o argumento listener agora produz a função listener original. |
v0.9.3 | Adicionado em: v0.9.3 |
eventName
<string> | <symbol> O nome do eventolistener
<Function> A função de tratamento de evento
O evento 'removeListener'
é emitido após o listener
ser 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 sincronamente cada um dos listeners registrados para o evento nomeado eventName
, na ordem em que foram registrados, passando os argumentos fornecidos para cada um.
Retorna true
se o evento tiver listeners, false
caso contrário.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
const EventEmitter = require('node:events');
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
emitter.eventNames()
Adicionado em: v6.0.0
- Retorna: <Array>
Retorna um array listando os eventos para os quais o emitter 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 de listener para o EventEmitter
que é definido por emitter.setMaxListeners(n)
ou o padrão é events.defaultMaxListeners
.
emitter.listenerCount(eventName[, listener])
[Histórico]
Versão | Mudanças |
---|---|
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 manipulador de eventos- Retorna: <integer>
Retorna o número de listeners escutando o evento nomeado eventName
. Se listener
for fornecido, ele 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 listeners anexados usando .once() , isso retorna os listeners originais em vez de funções wrapper agora. |
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 se 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
. Nenhuma verificação é feita para ver se o listener
já foi adicionado. Várias chamadas passando a mesma combinação de eventName
e listener
resultarão na adição do listener
e na chamada várias vezes.
server.on('connection', (stream) => {
console.log('alguém se conectou!');
});
Retorna uma referência ao EventEmitter
, para que as chamadas possam ser encadeadas.
Por padrão, os listeners de evento são invocados na ordem em que são adicionados. O método emitter.prependListener()
pode ser usado como uma 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 chamado eventName
. A próxima vez que o eventName
for acionado, este listener é 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 evento 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 evento 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');
// Prints:
// 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');
// Prints:
// 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 chamado eventName
. Nenhuma verificação é feita para verificar se o listener
já foi adicionado. Múltiplas chamadas passando a mesma combinação de eventName
e listener
resultarão na adição e chamada do listener
várias vezes.
server.prependListener('connection', (stream) => {
console.log('alguém 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 será removido e então 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 de EventEmitter
foi criada por algum outro componente ou módulo (ex: 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 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 algum listener individual foi adicionado múltiplas vezes ao array de listeners para o eventName
especificado, então removeListener()
deve ser chamado múltiplas 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 removeListener()
ou removeAllListeners()
após a emissão e antes que o último listener termine a execução não os removerá do emit()
em progresso. 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 foi 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 foi removido.
// Array interno de listeners [callbackA]
myEmitter.emit('event');
// Imprime:
// A
Como os listeners são gerenciados usando um array interno, chamar isso mudará os índices de posição de qualquer listener registrado após o listener sendo removido. Isso não afetará a ordem em que os listeners são chamados, mas significa que qualquer cópia do array de listeners retornado pelo método emitter.listeners()
precisará ser recriada.
Quando uma única função foi adicionada como um manipulador múltiplas 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 exibirã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 chamado 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'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
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 uma rejeição de promise aconteça ao emitir um evento e captureRejections
esteja 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('rejection happened for', event, 'with', err, ...args);
this.destroy(err);
}
destroy(err) {
// Tear the resource down here.
}
}
const { EventEmitter, captureRejectionSymbol } = require('node:events');
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejection happened for', event, 'with', err, ...args);
this.destroy(err);
}
destroy(err) {
// Tear the resource down here.
}
}
events.defaultMaxListeners
Adicionado em: v0.11.2
Por padrão, um máximo de 10
listeners podem ser registrados para qualquer evento único. 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 este valor não for um número positivo, um RangeError
é lançado.
Tome cuidado ao definir o events.defaultMaxListeners
porque 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 listeners sejam adicionados, mas exibirá um aviso de rastreamento para stderr indicando que um "possível vazamento de memória do EventEmitter" foi detectado. Para qualquer EventEmitter
único, 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', () => {
// 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));
});
O sinalizador de linha de comando --trace-warnings
pode ser usado 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 listeners 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 listener apenas para monitorar eventos 'error'
. Os listeners instalados usando este símbolo são chamados antes dos listeners 'error'
regulares.
Instalar um listener usando este símbolo não muda o comportamento quando um evento 'error'
é emitido. Portanto, o processo ainda travará se nenhum listener 'error'
regular 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 listeners 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 listeners de evento para o alvo 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('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)
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 emitter.
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>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 EventTarget da plataforma web, que não possui semântica especial de evento 'error'
e não escuta 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
', então ele é 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'));
// Prints: 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'));
// Prints: 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(); // Prints: 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(); // Prints: 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 sincronamente. Especificamente, como a fila process.nextTick()
é esvaziada antes da fila de microtarefas Promise
, e como EventEmitter
emite todos os eventos sincronamente, é 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>
Altera a opção captureRejections
padrão 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 determinado eventName
registrado no determinado emitter
.
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
const { EventEmitter, listenerCount } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 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 de espera.close
- <string[]> Nomes de eventos que encerrarão a iteração.highWaterMark
- <integer> Padrão:Number.MAX_SAFE_INTEGER
O limite superior. O emissor é pausado sempre que o tamanho dos eventos em buffer é maior que ele. Suportado apenas em emissores que implementam métodospause()
eresume()
.lowWaterMark
- <integer> Padrão:1
O limite inferior. O emissor é retomado sempre que o tamanho dos eventos em buffer é menor que ele. Suportado apenas em emissores que implementam 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 concorrente for necessária.
console.log(event); // imprime ['bar'] [42]
}
// Irrelevante 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 concorrente for necessária.
console.log(event); // imprime ['bar'] [42]
}
// Irrelevante aqui
})();
Retorna um AsyncIterator
que itera eventos eventName
. Lançará um erro se o EventEmitter
emitir 'error'
. Remove todos os listeners ao sair do loop. O value
retornado por cada iteração é um array composto pelos argumentos do evento emitido.
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 concorrente for necessária.
console.log(event); // imprime ['bar'] [42]
}
// Irrelevante 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 concorrente for necessária.
console.log(event); // imprime ['bar'] [42]
}
// Irrelevante 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
abort
.
Ouve uma vez o evento abort
no signal
fornecido.
Ouvir o evento abort
em sinais de aborto não é seguro e pode levar a vazamentos de recursos, pois outra entidade com o sinal pode 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.
Esta API permite usar AbortSignal
s com segurança nas APIs do Node.js, resolvendo esses dois problemas ao ouvir o evento de forma que stopImmediatePropagation
não impeça a execução do listener.
Retorna um disposable para que ele possa ser removido mais facilmente.
const { addAbortListener } = require('node:events');
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} 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) => {
// Do something when signal is aborted.
});
} 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 requerem 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';
// A ferramenta de rastreamento assíncrono identificará isso como 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// Os listeners '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 listeners '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 } from 'node:async_hooks';
// A ferramenta de rastreamento assíncrono identificará isso como 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// Os listeners '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 listeners '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
tem os mesmos métodos e recebe as mesmas opções que EventEmitter
e AsyncResource
.
new events.EventEmitterAsyncResource([options])
options
<Object>captureRejections
<boolean> Permite a captura automática da 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
, desativa oemitDestroy
quando o objeto é coletado pelo coletor de lixo. Geralmente, isso não precisa ser definido (mesmo queemitDestroy
seja chamado manualmente), a menos que oasyncId
do recurso seja recuperado e oemitDestroy
da API sensível seja chamado com ele. Quando definido comofalse
, a chamadaemitDestroy
na coleta de lixo ocorrerá somente se houver pelo menos um ganchodestroy
ativo. Padrão:false
.
eventemitterasyncresource.asyncId
- Type: <number> O
asyncId
exclusivo atribuído ao recurso.
eventemitterasyncresource.asyncResource
- Type: O <AsyncResource> subjacente.
O objeto AsyncResource
retornado tem uma propriedade eventEmitter
adicional 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 | tratamento de erros alterado 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('foo event happened!');
});
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.
Listener de Evento
Os listeners de evento registrados para um type
de evento podem ser funções JavaScript ou objetos com uma propriedade handleEvent
cujo valor é uma função.
Em ambos os casos, a função handler é invocada com o argumento event
passado para a função eventTarget.dispatchEvent()
.
Funções Async podem ser usadas como listeners de evento. Se uma função handler async rejeitar, a rejeição é capturada e tratada conforme descrito em tratamento de erros EventTarget
.
Um erro lançado por uma função handler não impede que os outros handlers sejam invocados.
O valor de retorno de uma função handler é ignorado.
Os handlers são sempre invocados na ordem em que foram adicionados.
As funções Handler podem alterar 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 em EventTarget
Quando um listener de evento registrado lança um erro (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 terminarão o processo do Node.js por padrão.
Lançar um erro dentro de um listener de evento não impedirá que os outros manipuladores 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 mudará 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
.
Isto não é usado no Node.js e é fornecido puramente para fins de integridade.
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
. Isto não é usado no Node.js e é fornecido puramente para fins de integridade.
event.cancelable
Adicionado em: v14.5.0
- Tipo: <boolean> True se o evento foi criado com a opção
cancelable
.
event.composed
Adicionado em: v14.5.0
- Tipo: <boolean> Sempre retorna
false
.
Isto não é usado no Node.js e é fornecido puramente para completude.
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. Isto não é usado no Node.js e é fornecido puramente para completude.
event.currentTarget
Adicionado em: v14.5.0
- Tipo: <EventTarget> O
EventTarget
despachando o evento.
Alias para event.target
.
event.defaultPrevented
Adicionado em: v14.5.0
- Tipo: <boolean>
É true
se cancelable
é true
e event.preventDefault()
foi 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.
Isto não é usado no Node.js e é fornecido puramente para completude.
event.initEvent(type[, bubbles[, cancelable]])
Adicionado em: v19.5.0
[Stable: 3 - Legacy]
Stable: 3 Estabilidade: 3 - Legado: A especificação WHATWG considera-o obsoleto e os usuários não devem usá-lo de forma alguma.
Redundante com os construtores de eventos e incapaz de definir composed
. Isto não é usado no Node.js e é fornecido puramente para completude.
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
. Isso não é usado no Node.js e é fornecido puramente para fins de integridade.
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
Impede a invocação de listeners de evento após a conclusão do atual.
event.stopPropagation()
Adicionado em: v14.5.0
Isso não é usado no Node.js e é fornecido puramente para fins de integridade.
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 | Mudanças |
---|---|
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 | Alterações |
---|---|
v15.4.0 | Adicionado 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 é automaticamente removido quando é invocado pela primeira vez. Padrão:false
.passive
<boolean> Quandotrue
, serve como uma dica de que o listener não irá chamar o métodopreventDefault()
do objetoEvent
. Padrão:false
.capture
<boolean> Não é usado diretamente pelo Node.js. Adicionado para completude 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 da opção capture
.
Se a opção once
for true
, o listener
é 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 forma 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 }); // first
target.addEventListener('foo', handler, { capture: false }); // second
// Remove a segunda instância do manipulador
target.removeEventListener('foo', handler);
// Remove a primeira instância do manipulador
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 se 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 sincronamente 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 type
de evento.
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 da 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 dados personalizados passados ao inicializar.
Somente leitura.
Classe: NodeEventTarget
Adicionado em: v14.5.0
- Estende: <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 ao EventTarget
.
nodeEventTarget.emit(type, arg)
Adicionado em: v15.2.0
type
<string>arg
<any>- Retorna: <boolean>
true
se ouvintes de evento registrados para otype
existirem, caso contráriofalse
.
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 evento para os quais os ouvintes de evento 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 evento 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 evento 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 evento.
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
.