Eventi
[Stabile: 2 - Stabile]
Stabile: 2 Stabilità: 2 - Stabile
Codice sorgente: lib/events.js
Gran parte dell'API principale di Node.js è costruita attorno a un'architettura asincrona idiomatica guidata dagli eventi in cui determinati tipi di oggetti (chiamati "emettitori") emettono eventi denominati che fanno sì che gli oggetti Function
("listener") vengano chiamati.
Ad esempio: un oggetto net.Server
emette un evento ogni volta che un peer si connette ad esso; un fs.ReadStream
emette un evento quando il file viene aperto; uno stream emette un evento ogni volta che i dati sono disponibili per essere letti.
Tutti gli oggetti che emettono eventi sono istanze della classe EventEmitter
. Questi oggetti espongono una funzione eventEmitter.on()
che consente di collegare una o più funzioni a eventi denominati emessi dall'oggetto. In genere, i nomi degli eventi sono stringhe in camel-case, ma è possibile utilizzare qualsiasi chiave di proprietà JavaScript valida.
Quando l'oggetto EventEmitter
emette un evento, tutte le funzioni collegate a quello specifico evento vengono chiamate sincronamente. Tutti i valori restituiti dai listener chiamati vengono ignorati e scartati.
L'esempio seguente mostra una semplice istanza EventEmitter
con un singolo listener. Il metodo eventEmitter.on()
viene utilizzato per registrare i listener, mentre il metodo eventEmitter.emit()
viene utilizzato per attivare l'evento.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
Passaggio di argomenti e this
ai listener
Il metodo eventEmitter.emit()
consente di passare un set arbitrario di argomenti alle funzioni listener. Tieni presente che quando viene chiamata una normale funzione listener, la parola chiave standard this
viene intenzionalmente impostata per fare riferimento all'istanza EventEmitter
a cui è collegato il listener.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// 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);
// Prints:
// 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');
È possibile utilizzare le Funzioni Arrow ES6 come listener, tuttavia, quando si fa ciò, la parola chiave this
non farà più riferimento all'istanza EventEmitter
:
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: 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);
// Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');
Asincrono vs. sincrono
L'EventEmitter
chiama tutti i listener in modo sincrono nell'ordine in cui sono stati registrati. Questo garantisce la corretta sequenza degli eventi e aiuta a evitare race condition ed errori logici. Quando appropriato, le funzioni listener possono passare a una modalità di funzionamento asincrona utilizzando i metodi setImmediate()
o process.nextTick()
:
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('questo accade in modo asincrono');
});
});
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('questo accade in modo asincrono');
});
});
myEmitter.emit('event', 'a', 'b');
Gestire gli eventi una sola volta
Quando un listener è registrato utilizzando il metodo eventEmitter.on()
, quel listener viene invocato ogni volta che l'evento denominato viene emesso.
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
Utilizzando il metodo eventEmitter.once()
, è possibile registrare un listener che viene chiamato al massimo una volta per un particolare evento. Una volta che l'evento viene emesso, il listener viene deregistrato e poi chiamato.
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
Eventi di errore
Quando si verifica un errore all'interno di un'istanza di EventEmitter
, l'azione tipica è l'emissione di un evento 'error'
. Questi sono trattati come casi speciali all'interno di Node.js.
Se un EventEmitter
non ha almeno un listener registrato per l'evento 'error'
, e viene emesso un evento 'error'
, l'errore viene lanciato, viene stampato uno stack trace e il processo Node.js si chiude.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Lancia un'eccezione e arresta Node.js
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Lancia un'eccezione e arresta Node.js
Per proteggersi dall'arresto anomalo del processo Node.js, è possibile utilizzare il modulo domain
. (Si noti, tuttavia, che il modulo node:domain
è deprecato.)
Come buona pratica, i listener devono sempre essere aggiunti per gli eventi '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!'));
// Stampa: 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!'));
// Stampa: whoops! there was an error
È possibile monitorare gli eventi 'error'
senza consumare l'errore emesso installando un listener usando il simbolo 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!'));
// Lancia ancora un'eccezione e arresta 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!'));
// Lancia ancora un'eccezione e arresta Node.js
Catturare i rifiuti delle promesse
L'uso di funzioni async
con gestori di eventi è problematico, perché può portare a un rifiuto non gestito in caso di eccezione lanciata:
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');
});
L'opzione captureRejections
nel costruttore EventEmitter
o l'impostazione globale modificano questo comportamento, installando un gestore .then(undefined, handler)
sulla Promise
. Questo gestore indirizza l'eccezione in modo asincrono al metodo Symbol.for('nodejs.rejection')
se presente, o al gestore di eventi 'error'
se non presente.
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;
Impostare events.captureRejections = true
cambierà il valore predefinito per tutte le nuove istanze di 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);
Gli eventi 'error'
che vengono generati dal comportamento captureRejections
non hanno un gestore catch per evitare loop di errore infiniti: la raccomandazione è di non usare funzioni async
come gestori di eventi 'error'
.
Classe: EventEmitter
[Cronologia]
Versione | Modifiche |
---|---|
v13.4.0, v12.16.0 | Aggiunta l'opzione captureRejections. |
v0.1.26 | Aggiunta in: v0.1.26 |
La classe EventEmitter
è definita ed esposta dal modulo node:events
:
import { EventEmitter } from 'node:events';
const EventEmitter = require('node:events');
Tutti gli EventEmitter
emettono l'evento 'newListener'
quando vengono aggiunti nuovi listener e 'removeListener'
quando i listener esistenti vengono rimossi.
Supporta la seguente opzione:
captureRejections
<boolean> Abilita l'acquisizione automatica del rifiuto della promessa. Predefinito:false
.
Evento: 'newListener'
Aggiunto in: v0.1.26
eventName
<string> | <symbol> Il nome dell'evento in ascoltolistener
<Function> La funzione handler dell'evento
L'istanza EventEmitter
emetterà il proprio evento 'newListener'
prima che un listener venga aggiunto al suo array interno di listener.
Ai listener registrati per l'evento 'newListener'
vengono passati il nome dell'evento e un riferimento al listener che viene aggiunto.
Il fatto che l'evento venga attivato prima di aggiungere il listener ha un effetto collaterale sottile ma importante: qualsiasi listener aggiuntivo registrato allo stesso name
all'interno del callback 'newListener'
viene inserito prima del listener che è in fase di aggiunta.
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Fallo solo una volta in modo da non andare in loop all'infinito
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Inserisci un nuovo listener davanti
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Stampa:
// B
// A
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Fallo solo una volta in modo da non andare in loop all'infinito
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Inserisci un nuovo listener davanti
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Stampa:
// B
// A
Evento: 'removeListener'
[Cronologia]
Versione | Modifiche |
---|---|
v6.1.0, v4.7.0 | Per i listener collegati tramite .once() , l'argomento listener ora restituisce la funzione listener originale. |
v0.9.3 | Aggiunto in: v0.9.3 |
eventName
<string> | <symbol> Il nome dell'eventolistener
<Function> La funzione di gestione dell'evento
L'evento 'removeListener'
viene emesso dopo che il listener
è stato rimosso.
emitter.addListener(eventName, listener)
Aggiunto in: v0.1.26
eventName
<string> | <symbol>listener
<Function>
Alias per emitter.on(eventName, listener)
.
emitter.emit(eventName[, ...args])
Aggiunto in: v0.1.26
Chiama in modo sincrono ciascuno dei listener registrati per l'evento denominato eventName
, nell'ordine in cui sono stati registrati, passando a ciascuno gli argomenti forniti.
Restituisce true
se l'evento aveva dei listener, false
altrimenti.
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// Primo listener
myEmitter.on('event', function firstListener() {
console.log('Ciao! primo listener');
});
// Secondo listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`evento con parametri ${arg1}, ${arg2} nel secondo listener`);
});
// Terzo listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`evento con parametri ${parameters} nel terzo listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Ciao! primo listener
// evento con parametri 1, 2 nel secondo listener
// evento con parametri 1, 2, 3, 4, 5 nel terzo listener
const EventEmitter = require('node:events');
const myEmitter = new EventEmitter();
// Primo listener
myEmitter.on('event', function firstListener() {
console.log('Ciao! primo listener');
});
// Secondo listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`evento con parametri ${arg1}, ${arg2} nel secondo listener`);
});
// Terzo listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`evento con parametri ${parameters} nel terzo listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Ciao! primo listener
// evento con parametri 1, 2 nel secondo listener
// evento con parametri 1, 2, 3, 4, 5 nel terzo listener
emitter.eventNames()
Aggiunto in: v6.0.0
- Restituisce: <Array>
Restituisce un array elencando gli eventi per i quali l'emettitore ha registrato dei listener. I valori nell'array sono stringhe o Symbol
.
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());
// Prints: [ '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());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
Aggiunto in: v1.0.0
- Restituisce: <integer>
Restituisce il valore massimo attuale del listener per EventEmitter
che è impostato da emitter.setMaxListeners(n)
o predefinito a events.defaultMaxListeners
.
emitter.listenerCount(eventName[, listener])
[Cronologia]
Versione | Modifiche |
---|---|
v19.8.0, v18.16.0 | Aggiunto l'argomento listener . |
v3.2.0 | Aggiunto in: v3.2.0 |
eventName
<string> | <symbol> Il nome dell'evento in ascoltolistener
<Function> La funzione di gestione dell'evento- Restituisce: <integer>
Restituisce il numero di listener in ascolto dell'evento denominato eventName
. Se viene fornito listener
, restituirà quante volte il listener viene trovato nell'elenco dei listener dell'evento.
emitter.listeners(eventName)
[Cronologia]
Versione | Modifiche |
---|---|
v7.0.0 | Per i listener collegati tramite .once() ora restituisce i listener originali invece delle funzioni wrapper. |
v0.1.26 | Aggiunto in: v0.1.26 |
eventName
<stringa> | <simbolo>- Restituisce: <Function[]>
Restituisce una copia dell'array di listener per l'evento denominato eventName
.
server.on('connection', (stream) => {
console.log('qualcuno si è connesso!');
});
console.log(util.inspect(server.listeners('connection')));
// Stampa: [ [Function] ]
emitter.off(eventName, listener)
Aggiunto in: v10.0.0
eventName
<stringa> | <simbolo>listener
<Funzione>- Restituisce: <EventEmitter>
Alias per emitter.removeListener()
.
emitter.on(eventName, listener)
Aggiunto in: v0.1.101
eventName
<stringa> | <simbolo> Il nome dell'evento.listener
<Funzione> La funzione di callback- Restituisce: <EventEmitter>
Aggiunge la funzione listener
alla fine dell'array dei listener per l'evento denominato eventName
. Non vengono effettuati controlli per vedere se il listener
è già stato aggiunto. Più chiamate che passano la stessa combinazione di eventName
e listener
comporteranno l'aggiunta del listener
e la sua chiamata più volte.
server.on('connection', (stream) => {
console.log('qualcuno si è connesso!');
});
Restituisce un riferimento all'EventEmitter
, in modo che le chiamate possano essere concatenate.
Per impostazione predefinita, i listener degli eventi vengono richiamati nell'ordine in cui vengono aggiunti. Il metodo emitter.prependListener()
può essere utilizzato in alternativa per aggiungere il listener dell'evento all'inizio dell'array dei listener.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Stampa:
// 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');
// Stampa:
// b
// a
emitter.once(eventName, listener)
Aggiunto in: v0.3.0
eventName
<stringa> | <simbolo> Il nome dell'evento.listener
<Funzione> La funzione di callback- Restituisce: <EventEmitter>
Aggiunge una funzione listener
una tantum per l'evento chiamato eventName
. La prossima volta che eventName
viene attivato, questo listener viene rimosso e quindi invocato.
server.once('connection', (stream) => {
console.log('Ah, abbiamo il nostro primo utente!');
});
Restituisce un riferimento a EventEmitter
, in modo che le chiamate possano essere concatenate.
Per impostazione predefinita, i listener di eventi vengono invocati nell'ordine in cui vengono aggiunti. Il metodo emitter.prependOnceListener()
può essere utilizzato come alternativa per aggiungere il listener di eventi all'inizio dell'array dei listener.
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Stampa:
// 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');
// Stampa:
// b
// a
emitter.prependListener(eventName, listener)
Aggiunto in: v6.0.0
eventName
<stringa> | <simbolo> Il nome dell'evento.listener
<Funzione> La funzione di callback- Restituisce: <EventEmitter>
Aggiunge la funzione listener
all'inizio dell'array di listener per l'evento chiamato eventName
. Non vengono eseguiti controlli per verificare se il listener
è già stato aggiunto. Più chiamate che passano la stessa combinazione di eventName
e listener
comporteranno l'aggiunta e la chiamata del listener
più volte.
server.prependListener('connection', (stream) => {
console.log('qualcuno si è connesso!');
});
Restituisce un riferimento a EventEmitter
, in modo che le chiamate possano essere concatenate.
emitter.prependOnceListener(eventName, listener)
Aggiunto in: v6.0.0
eventName
<stringa> | <simbolo> Il nome dell'evento.listener
<Funzione> La funzione di callback- Restituisce: <EventEmitter>
Aggiunge una funzione listener
una-tantum per l'evento denominato eventName
all'inizio dell'array dei listener. La prossima volta che eventName
viene attivato, questo listener viene rimosso, e quindi invocato.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, abbiamo il nostro primo utente!');
});
Restituisce un riferimento all'EventEmitter
, in modo che le chiamate possano essere concatenate.
emitter.removeAllListeners([eventName])
Aggiunto in: v0.1.26
eventName
<stringa> | <simbolo>- Restituisce: <EventEmitter>
Rimuove tutti i listener, o quelli dello specifico eventName
.
È una cattiva pratica rimuovere i listener aggiunti altrove nel codice, in particolare quando l'istanza di EventEmitter
è stata creata da qualche altro componente o modulo (ad esempio socket o flussi di file).
Restituisce un riferimento all'EventEmitter
, in modo che le chiamate possano essere concatenate.
emitter.removeListener(eventName, listener)
Aggiunto in: v0.1.26
eventName
<stringa> | <simbolo>listener
<Funzione>- Restituisce: <EventEmitter>
Rimuove lo specifico listener
dall'array dei listener per l'evento denominato eventName
.
const callback = (stream) => {
console.log('qualcuno si è connesso!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
removeListener()
rimuoverà, al massimo, un'istanza di un listener dall'array dei listener. Se un qualsiasi singolo listener è stato aggiunto più volte all'array dei listener per lo specifico eventName
, allora removeListener()
deve essere chiamato più volte per rimuovere ciascuna istanza.
Una volta che un evento viene emesso, tutti i listener ad esso collegati al momento dell'emissione vengono chiamati in ordine. Ciò implica che qualsiasi chiamata a removeListener()
o removeAllListeners()
dopo l'emissione e prima che l'ultimo listener termini l'esecuzione non li rimuoverà da emit()
in corso. Gli eventi successivi si comportano come previsto.
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 rimuove il listener callbackB ma verrà comunque chiamato.
// Array di listener interno al momento dell'emissione [callbackA, callbackB]
myEmitter.emit('event');
// Stampa:
// A
// B
// callbackB è ora rimosso.
// Array di listener interno [callbackA]
myEmitter.emit('event');
// Stampa:
// 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 rimuove il listener callbackB ma verrà comunque chiamato.
// Array di listener interno al momento dell'emissione [callbackA, callbackB]
myEmitter.emit('event');
// Stampa:
// A
// B
// callbackB è ora rimosso.
// Array di listener interno [callbackA]
myEmitter.emit('event');
// Stampa:
// A
Poiché i listener vengono gestiti utilizzando un array interno, chiamare questo cambierà gli indici di posizione di qualsiasi listener registrato dopo il listener che viene rimosso. Ciò non influirà sull'ordine in cui vengono chiamati i listener, ma significa che qualsiasi copia dell'array dei listener come restituito dal metodo emitter.listeners()
dovrà essere ricreata.
Quando una singola funzione è stata aggiunta come gestore più volte per un singolo evento (come nell'esempio seguente), removeListener()
rimuoverà l'istanza aggiunta più di recente. Nell'esempio viene rimosso il listener once('ping')
:
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
const EventEmitter = require('node:events');
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
Restituisce un riferimento all'EventEmitter
, in modo che le chiamate possano essere concatenate.
emitter.setMaxListeners(n)
Aggiunto in: v0.3.5
n
<integer>- Restituisce: <EventEmitter>
Per impostazione predefinita, gli EventEmitter
stamperanno un avviso se vengono aggiunti più di 10
listener per un evento specifico. Questo è un valore predefinito utile che aiuta a trovare perdite di memoria. Il metodo emitter.setMaxListeners()
consente di modificare il limite per questa specifica istanza di EventEmitter
. Il valore può essere impostato su Infinity
(o 0
) per indicare un numero illimitato di listener.
Restituisce un riferimento all'EventEmitter
, in modo che le chiamate possano essere concatenate.
emitter.rawListeners(eventName)
Aggiunto in: v9.4.0
eventName
<stringa> | <simbolo>- Restituisce: <Funzione[]>
Restituisce una copia dell'array di listener per l'evento denominato eventName
, inclusi eventuali wrapper (come quelli creati da .once()
).
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Restituisce un nuovo Array con una funzione `onceWrapper` che ha una proprietà
// `listener` che contiene il listener originale associato sopra
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Registra "log once" sulla console e non scollega l'evento `once`
logFnWrapper.listener();
// Registra "log once" sulla console e rimuove il listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Restituirà un nuovo Array con una singola funzione associata da `.on()` sopra
const newListeners = emitter.rawListeners('log');
// Registra "log persistently" due volte
newListeners[0]();
emitter.emit('log');
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Restituisce un nuovo Array con una funzione `onceWrapper` che ha una proprietà
// `listener` che contiene il listener originale associato sopra
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Registra "log once" sulla console e non scollega l'evento `once`
logFnWrapper.listener();
// Registra "log once" sulla console e rimuove il listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Restituirà un nuovo Array con una singola funzione associata da `.on()` sopra
const newListeners = emitter.rawListeners('log');
// Registra "log persistently" due volte
newListeners[0]();
emitter.emit('log');
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
[Cronologia]
Versione | Modifiche |
---|---|
v17.4.0, v16.14.0 | Non più sperimentale. |
v13.4.0, v12.16.0 | Aggiunto in: v13.4.0, v12.16.0 |
err
ErroreeventName
<stringa> | <simbolo>...args
<qualsiasi>
Il metodo Symbol.for('nodejs.rejection')
viene chiamato nel caso in cui si verifichi un rifiuto di una promise durante l'emissione di un evento e captureRejections
sia abilitato sull'emettitore. È possibile utilizzare events.captureRejectionSymbol
al posto di Symbol.for('nodejs.rejection')
.
import { EventEmitter, captureRejectionSymbol } from 'node:events';
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('si è verificato un rifiuto per', event, 'con', err, ...args);
this.destroy(err);
}
destroy(err) {
// Abbattere la risorsa qui.
}
}
const { EventEmitter, captureRejectionSymbol } = require('node:events');
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('si è verificato un rifiuto per', event, 'con', err, ...args);
this.destroy(err);
}
destroy(err) {
// Abbattere la risorsa qui.
}
}
events.defaultMaxListeners
Aggiunto in: v0.11.2
Per impostazione predefinita, è possibile registrare un massimo di 10
listener per un singolo evento. Questo limite può essere modificato per le singole istanze di EventEmitter
utilizzando il metodo emitter.setMaxListeners(n)
. Per modificare il valore predefinito per tutte le istanze di EventEmitter
, è possibile utilizzare la proprietà events.defaultMaxListeners
. Se questo valore non è un numero positivo, viene generato un RangeError
.
Prestare attenzione quando si imposta events.defaultMaxListeners
perché la modifica influisce su tutte le istanze di EventEmitter
, comprese quelle create prima che la modifica venga apportata. Tuttavia, la chiamata a emitter.setMaxListeners(n)
ha comunque la precedenza su events.defaultMaxListeners
.
Questo non è un limite rigido. L'istanza di EventEmitter
consentirà l'aggiunta di più listener, ma emetterà un avviso di traccia su stderr indicando che è stata rilevata una "possibile perdita di memoria di EventEmitter". Per qualsiasi singolo EventEmitter
, i metodi emitter.getMaxListeners()
e emitter.setMaxListeners()
possono essere utilizzati per evitare temporaneamente questo avviso:
defaultMaxListeners
non ha effetto sulle istanze di AbortSignal
. Sebbene sia ancora possibile utilizzare emitter.setMaxListeners(n)
per impostare un limite di avviso per le singole istanze di AbortSignal
, per impostazione predefinita le istanze di AbortSignal
non avviseranno.
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// fare qualcosa
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', () => {
// fare qualcosa
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
Il flag della riga di comando --trace-warnings
può essere utilizzato per visualizzare la traccia dello stack per tali avvisi.
L'avviso emesso può essere ispezionato con process.on('warning')
e avrà le proprietà aggiuntive emitter
, type
e count
, che si riferiscono rispettivamente all'istanza dell'emettitore di eventi, al nome dell'evento e al numero di listener collegati. La sua proprietà name
è impostata su 'MaxListenersExceededWarning'
.
events.errorMonitor
Aggiunto in: v13.6.0, v12.17.0
Questo simbolo deve essere utilizzato per installare un listener solo per il monitoraggio degli eventi 'error'
. I listener installati utilizzando questo simbolo vengono chiamati prima dei normali listener 'error'
.
L'installazione di un listener tramite questo simbolo non modifica il comportamento una volta emesso un evento 'error'
. Pertanto, il processo si arresterà comunque in modo anomalo se non è installato alcun listener 'error'
regolare.
events.getEventListeners(emitterOrTarget, eventName)
Aggiunto in: v15.2.0, v14.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>eventName
<string> | <symbol>- Restituisce: <Function[]>
Restituisce una copia dell'array di listener per l'evento denominato eventName
.
Per EventEmitter
si comporta esattamente come chiamare .listeners
sull'emitter.
Per EventTarget
questo è l'unico modo per ottenere i listener dell'evento per il target dell'evento. Questo è utile per il debug e la diagnostica.
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)
Aggiunto in: v19.9.0, v18.17.0
emitterOrTarget
<EventEmitter> | <EventTarget>- Restituisce: <number>
Restituisce la quantità massima di listener attualmente impostata.
Per gli EventEmitter
, questo si comporta esattamente come chiamare .getMaxListeners
sull'emitter.
Per gli EventTarget
, questo è l'unico modo per ottenere il numero massimo di listener di eventi per l'event target. Se il numero di gestori di eventi su un singolo EventTarget supera il massimo impostato, l'EventTarget stamperà un avviso.
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])
[Cronologia]
Versione | Modifiche |
---|---|
v15.0.0 | L'opzione signal è ora supportata. |
v11.13.0, v10.16.0 | Aggiunto in: v11.13.0, v10.16.0 |
emitter
<EventEmitter>options
<Object>signal
<AbortSignal> Può essere utilizzato per annullare l'attesa per l'evento.
Restituisce: <Promise>
Crea una Promise
che viene soddisfatta quando l'EventEmitter
emette l'evento specificato o che viene rifiutata se l'EventEmitter
emette 'error'
durante l'attesa. La Promise
si risolverà con un array di tutti gli argomenti emessi all'evento specificato.
Questo metodo è intenzionalmente generico e funziona con l'interfaccia EventTarget della piattaforma web, che non ha una semantica speciale per l'evento 'error'
e non ascolta l'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();
La gestione speciale dell'evento 'error'
viene utilizzata solo quando events.once()
viene utilizzato per attendere un altro evento. Se events.once()
viene utilizzato per attendere l'evento 'error
' stesso, allora viene trattato come qualsiasi altro tipo di evento senza una gestione speciale:
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
Un <AbortSignal> può essere utilizzato per annullare l'attesa per l'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!
Attesa di molteplici eventi emessi su process.nextTick()
Esiste un caso limite degno di nota quando si utilizza la funzione events.once()
per attendere più eventi emessi nello stesso batch di operazioni process.nextTick()
, o ogni volta che più eventi vengono emessi in modo sincrono. In particolare, poiché la coda process.nextTick()
viene svuotata prima della coda dei microtask Promise
, e poiché EventEmitter
emette tutti gli eventi in modo sincrono, è possibile che events.once()
perda un evento.
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// Questa Promise non si risolverà mai perché l'evento 'foo' sarà
// già stato emesso prima che la Promise venga creata.
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');
// Questa Promise non si risolverà mai perché l'evento 'foo' sarà
// già stato emesso prima che la Promise venga creata.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
Per intercettare entrambi gli eventi, crea ciascuna delle Promise prima di attenderne una qualsiasi, quindi diventa possibile utilizzare Promise.all()
, Promise.race()
o Promise.allSettled()
:
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
events.captureRejections
[Cronologia]
Versione | Modifiche |
---|---|
v17.4.0, v16.14.0 | Non più sperimentale. |
v13.4.0, v12.16.0 | Aggiunto in: v13.4.0, v12.16.0 |
Valore: <boolean>
Cambia l'opzione predefinita captureRejections
su tutti i nuovi oggetti EventEmitter
.
events.captureRejectionSymbol
[Cronologia]
Versione | Modifiche |
---|---|
v17.4.0, v16.14.0 | Non più sperimentale. |
v13.4.0, v12.16.0 | Aggiunto in: v13.4.0, v12.16.0 |
Valore: Symbol.for('nodejs.rejection')
Vedi come scrivere un gestore di reiezione personalizzato.
events.listenerCount(emitter, eventName)
Aggiunto in: v0.9.12
Deprecato dal: v3.2.0
[Stabile: 0 - Deprecato]
Stabile: 0 Stabilità: 0 - Deprecato: Utilizza invece emitter.listenerCount()
.
emitter
<EventEmitter> L'emettitore da interrogareeventName
<string> | <symbol> Il nome dell'evento
Un metodo di classe che restituisce il numero di listener per l'eventName
dato registrato sull'emitter
dato.
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])
[Cronologia]
Versione | Modifiche |
---|---|
v22.0.0, v20.13.0 | Supporta le opzioni highWaterMark e lowWaterMark , per coerenza. Le vecchie opzioni sono ancora supportate. |
v20.0.0 | Le opzioni close , highWatermark e lowWatermark sono ora supportate. |
v13.6.0, v12.16.0 | Aggiunto in: v13.6.0, v12.16.0 |
emitter
<EventEmitter>eventName
<string> | <symbol> Il nome dell'evento in ascoltooptions
<Object>signal
<AbortSignal> Può essere usato per annullare gli eventi in attesa.close
- <string[]> Nomi di eventi che termineranno l'iterazione.highWaterMark
- <integer> Predefinito:Number.MAX_SAFE_INTEGER
Il limite massimo. L'emettitore viene messo in pausa ogni volta che la dimensione degli eventi in buffer è superiore a questo valore. Supportato solo sugli emettitori che implementano i metodipause()
eresume()
.lowWaterMark
- <integer> Predefinito:1
Il limite inferiore. L'emettitore viene ripreso ogni volta che la dimensione degli eventi in buffer è inferiore a questo valore. Supportato solo sugli emettitori che implementano i metodipause()
eresume()
.
Restituisce: <AsyncIterator> che itera sugli eventi
eventName
emessi dall'emitter
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emetti più tardi
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// L'esecuzione di questo blocco interno è sincrona ed elabora
// un evento alla volta (anche con await). Non usare
// se è richiesta l'esecuzione concorrente.
console.log(event); // stampa ['bar'] [42]
}
// Irraggiungibile qui
const { on, EventEmitter } = require('node:events');
(async () => {
const ee = new EventEmitter();
// Emetti più tardi
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// L'esecuzione di questo blocco interno è sincrona ed elabora
// un evento alla volta (anche con await). Non usare
// se è richiesta l'esecuzione concorrente.
console.log(event); // stampa ['bar'] [42]
}
// Irraggiungibile qui
})();
Restituisce un AsyncIterator
che itera sugli eventi eventName
. Verrà generata un'eccezione se l'EventEmitter
emette 'error'
. Rimuove tutti i listener quando si esce dal loop. Il value
restituito da ogni iterazione è un array composto dagli argomenti dell'evento emesso.
Un <AbortSignal> può essere utilizzato per annullare l'attesa degli eventi:
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emetti più tardi
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// L'esecuzione di questo blocco interno è sincrona ed elabora
// un evento alla volta (anche con await). Non usare
// se è richiesta l'esecuzione concorrente.
console.log(event); // stampa ['bar'] [42]
}
// Irraggiungibile qui
})();
process.nextTick(() => ac.abort());
const { on, EventEmitter } = require('node:events');
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emetti più tardi
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// L'esecuzione di questo blocco interno è sincrona ed elabora
// un evento alla volta (anche con await). Non usare
// se è richiesta l'esecuzione concorrente.
console.log(event); // stampa ['bar'] [42]
}
// Irraggiungibile qui
})();
process.nextTick(() => ac.abort());
events.setMaxListeners(n[, ...eventTargets])
Aggiunto in: v15.4.0
n
<number> Un numero non negativo. Il numero massimo di listener per eventoEventTarget
....eventsTargets
<EventTarget[]> | <EventEmitter[]> Zero o più istanze di <EventTarget> o <EventEmitter>. Se non ne vengono specificate,n
viene impostato come valore massimo predefinito per tutti gli oggetti <EventTarget> e <EventEmitter> appena creati.
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)
Aggiunto in: v20.5.0, v18.18.0
[Stabile: 1 - Sperimentale]
Stabile: 1 Stabilità: 1 - Sperimentale
signal
<AbortSignal>listener
<Function> | <EventListener>- Restituisce: <Disposable> Un Disposable che rimuove il listener
abort
.
Ascolta una volta l'evento abort
sul signal
fornito.
Ascoltare l'evento abort
sui segnali di interruzione non è sicuro e può portare a perdite di risorse poiché un'altra terza parte con il segnale può chiamare e.stopImmediatePropagation()
. Sfortunatamente Node.js non può cambiarlo poiché violerebbe lo standard web. Inoltre, l'API originale rende facile dimenticare di rimuovere i listener.
Questa API consente di utilizzare in modo sicuro gli AbortSignal
nelle API di Node.js risolvendo questi due problemi ascoltando l'evento in modo tale che stopImmediatePropagation
non impedisca l'esecuzione del listener.
Restituisce un disposable in modo che possa essere disiscritta più 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
Aggiunto in: v17.4.0, v16.14.0
Integra EventEmitter
con <AsyncResource> per EventEmitter
che richiedono il tracciamento asincrono manuale. Nello specifico, tutti gli eventi emessi dalle istanze di events.EventEmitterAsyncResource
verranno eseguiti all'interno del suo contesto asincrono.
import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
import { notStrictEqual, strictEqual } from 'node:assert';
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';
// Gli strumenti di tracciamento asincrono lo identificheranno come 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// I listener 'foo' verranno eseguiti nel contesto asincrono degli EventEmitter.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// I listener 'foo' su EventEmitter ordinari che non tracciano il contesto
// asincrono, tuttavia, vengono eseguiti nello stesso contesto asincrono di 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');
// Gli strumenti di tracciamento asincrono lo identificheranno come 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// I listener 'foo' verranno eseguiti nel contesto asincrono degli EventEmitter.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// I listener 'foo' su EventEmitter ordinari che non tracciano il contesto
// asincrono, tuttavia, vengono eseguiti nello stesso contesto asincrono di emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});
La classe EventEmitterAsyncResource
ha gli stessi metodi e accetta le stesse opzioni di EventEmitter
e AsyncResource
stessi.
new events.EventEmitterAsyncResource([options])
options
<Object>captureRejections
<boolean> Abilita l'acquisizione automatica del rifiuto delle promise. Predefinito:false
.name
<string> Il tipo di evento asincrono. Predefinito:new.target.name
.triggerAsyncId
<number> L'ID del contesto di esecuzione che ha creato questo evento asincrono. Predefinito:executionAsyncId()
.requireManualDestroy
<boolean> Se impostato sutrue
, disabilitaemitDestroy
quando l'oggetto viene raccolto dal Garbage Collector. Di solito non è necessario impostarlo (anche seemitDestroy
viene chiamato manualmente), a meno che l'asyncId
della risorsa non venga recuperato e venga chiamata laemitDestroy
dell'API sensibile con esso. Quando impostato sufalse
, la chiamataemitDestroy
sul Garbage Collection avverrà solo se è presente almeno un hookdestroy
attivo. Predefinito:false
.
eventemitterasyncresource.asyncId
- Tipo: <number> L'
asyncId
univoco assegnato alla risorsa.
eventemitterasyncresource.asyncResource
- Tipo: <AsyncResource> sottostante.
L'oggetto AsyncResource
restituito ha una proprietà eventEmitter
aggiuntiva che fornisce un riferimento a questo EventEmitterAsyncResource
.
eventemitterasyncresource.emitDestroy()
Chiama tutti gli hook destroy
. Questo dovrebbe essere chiamato solo una volta. Verrà generato un errore se viene chiamato più di una volta. Questo deve essere chiamato manualmente. Se la risorsa viene lasciata alla raccolta da parte del GC, gli hook destroy
non verranno mai chiamati.
eventemitterasyncresource.triggerAsyncId
- Type: <number> Lo stesso
triggerAsyncId
passato al costruttore diAsyncResource
.
API EventTarget
ed Event
[Cronologia]
Versione | Modifiche |
---|---|
v16.0.0 | Gestione degli errori di EventTarget modificata. |
v15.4.0 | Non più sperimentale. |
v15.0.0 | Le classi EventTarget ed Event sono ora disponibili come globali. |
v14.5.0 | Aggiunto in: v14.5.0 |
Gli oggetti EventTarget
ed Event
sono un'implementazione specifica di Node.js della EventTarget
Web API che sono esposti da alcune API principali di Node.js.
const target = new EventTarget();
target.addEventListener('foo', (event) => {
console.log('evento foo accaduto!');
});
EventTarget
di Node.js contro EventTarget
DOM
Ci sono due differenze fondamentali tra EventTarget
di Node.js e la EventTarget
Web API:
NodeEventTarget
contro EventEmitter
L'oggetto NodeEventTarget
implementa un sottoinsieme modificato dell'API EventEmitter
che gli consente di emulare da vicino un EventEmitter
in determinate situazioni. Un NodeEventTarget
non è un'istanza di EventEmitter
e non può essere utilizzato al posto di un EventEmitter
nella maggior parte dei casi.
Listener di eventi
I listener di eventi registrati per un type
di evento possono essere funzioni JavaScript o oggetti con una proprietà handleEvent
il cui valore è una funzione.
In entrambi i casi, la funzione handler viene invocata con l'argomento event
passato alla funzione eventTarget.dispatchEvent()
.
Le funzioni asincrone possono essere utilizzate come listener di eventi. Se una funzione handler asincrona viene rifiutata, il rifiuto viene acquisito e gestito come descritto in gestione degli errori di EventTarget
.
Un errore generato da una funzione handler non impedisce l'invocazione degli altri handler.
Il valore restituito di una funzione handler viene ignorato.
Gli handler vengono sempre invocati nell'ordine in cui sono stati aggiunti.
Le funzioni handler possono mutare l'oggetto event
.
function handler1(event) {
console.log(event.type); // Stampa 'foo'
event.a = 1;
}
async function handler2(event) {
console.log(event.type); // Stampa 'foo'
console.log(event.a); // Stampa 1
}
const handler3 = {
handleEvent(event) {
console.log(event.type); // Stampa 'foo'
},
};
const handler4 = {
async handleEvent(event) {
console.log(event.type); // Stampa 'foo'
},
};
const target = new EventTarget();
target.addEventListener('foo', handler1);
target.addEventListener('foo', handler2);
target.addEventListener('foo', handler3);
target.addEventListener('foo', handler4, { once: true });
Gestione degli errori in EventTarget
Quando un listener di eventi registrato genera un'eccezione (o restituisce una Promise che viene rifiutata), per impostazione predefinita l'errore viene trattato come un'eccezione non gestita su process.nextTick()
. Ciò significa che le eccezioni non gestite in EventTarget
termineranno il processo di Node.js per impostazione predefinita.
Generare un'eccezione all'interno di un listener di eventi non impedirà l'invocazione degli altri handler registrati.
EventTarget
non implementa alcuna gestione predefinita speciale per gli eventi di tipo 'error'
come EventEmitter
.
Attualmente, gli errori vengono prima inoltrati all'evento process.on('error')
prima di raggiungere process.on('uncaughtException')
. Questo comportamento è deprecato e cambierà in una versione futura per allineare EventTarget
con altre API di Node.js. Qualsiasi codice che si basa sull'evento process.on('error')
deve essere allineato al nuovo comportamento.
Classe: Event
[Cronologia]
Versione | Modifiche |
---|---|
v15.0.0 | La classe Event è ora disponibile tramite l'oggetto globale. |
v14.5.0 | Aggiunta in: v14.5.0 |
L'oggetto Event
è un adattamento della Event
Web API. Le istanze vengono create internamente da Node.js.
event.bubbles
Aggiunta in: v14.5.0
- Tipo: <boolean> Restituisce sempre
false
.
Questo non viene utilizzato in Node.js ed è fornito puramente per completezza.
event.cancelBubble
Aggiunta in: v14.5.0
[Stabile: 3 - Legacy]
Stabile: 3 Stabilità: 3 - Legacy: utilizzare event.stopPropagation()
invece.
- Tipo: <boolean>
Alias per event.stopPropagation()
se impostato su true
. Questo non viene utilizzato in Node.js ed è fornito puramente per completezza.
event.cancelable
Aggiunta in: v14.5.0
- Tipo: <boolean> True se l'evento è stato creato con l'opzione
cancelable
.
event.composed
Aggiunto in: v14.5.0
- Tipo: <boolean> Restituisce sempre
false
.
Questo non è utilizzato in Node.js ed è fornito puramente per completezza.
event.composedPath()
Aggiunto in: v14.5.0
Restituisce un array contenente l'EventTarget
corrente come unica voce o vuoto se l'evento non viene distribuito. Questo non è utilizzato in Node.js ed è fornito puramente per completezza.
event.currentTarget
Aggiunto in: v14.5.0
- Tipo: <EventTarget> L'
EventTarget
che distribuisce l'evento.
Alias per event.target
.
event.defaultPrevented
Aggiunto in: v14.5.0
- Tipo: <boolean>
È true
se cancelable
è true
e event.preventDefault()
è stato chiamato.
event.eventPhase
Aggiunto in: v14.5.0
- Tipo: <number> Restituisce
0
mentre un evento non viene distribuito,2
mentre viene distribuito.
Questo non è utilizzato in Node.js ed è fornito puramente per completezza.
event.initEvent(type[, bubbles[, cancelable]])
Aggiunto in: v19.5.0
[Stabile: 3 - Legacy]
Stabile: 3 Stabilità: 3 - Legacy: La specifica WHATWG lo considera deprecato e gli utenti non dovrebbero usarlo affatto.
Ridondante con i costruttori di eventi e incapace di impostare composed
. Questo non è utilizzato in Node.js ed è fornito puramente per completezza.
event.isTrusted
Aggiunto in: v14.5.0
- Tipo: <boolean>
L'evento "abort"
di <AbortSignal> viene emesso con isTrusted
impostato su true
. Il valore è false
in tutti gli altri casi.
event.preventDefault()
Aggiunto in: v14.5.0
Imposta la proprietà defaultPrevented
su true
se cancelable
è true
.
event.returnValue
Aggiunto in: v14.5.0
[Stabile: 3 - Legacy]
Stabile: 3 Stabilità: 3 - Legacy: Utilizzare invece event.defaultPrevented
.
- Tipo: <boolean> True se l'evento non è stato annullato.
Il valore di event.returnValue
è sempre l'opposto di event.defaultPrevented
. Questo non viene utilizzato in Node.js ed è fornito puramente a scopo di completezza.
event.srcElement
Aggiunto in: v14.5.0
[Stabile: 3 - Legacy]
Stabile: 3 Stabilità: 3 - Legacy: Utilizzare invece event.target
.
- Tipo: <EventTarget> L'
EventTarget
che distribuisce l'evento.
Alias per event.target
.
event.stopImmediatePropagation()
Aggiunto in: v14.5.0
Interrompe l'invocazione dei listener di eventi dopo che quello corrente è stato completato.
event.stopPropagation()
Aggiunto in: v14.5.0
Questo non viene utilizzato in Node.js ed è fornito puramente a scopo di completezza.
event.target
Aggiunto in: v14.5.0
- Tipo: <EventTarget> L'
EventTarget
che distribuisce l'evento.
event.timeStamp
Aggiunto in: v14.5.0
- Tipo: <number>
Il timestamp in millisecondi quando è stato creato l'oggetto Event
.
event.type
Aggiunto in: v14.5.0
- Tipo: <string>
L'identificatore del tipo di evento.
Classe: EventTarget
[Cronologia]
Versione | Modifiche |
---|---|
v15.0.0 | La classe EventTarget è ora disponibile tramite l'oggetto globale. |
v14.5.0 | Aggiunto in: v14.5.0 |
eventTarget.addEventListener(type, listener[, options])
[Cronologia]
Versione | Modifiche |
---|---|
v15.4.0 | Aggiunto il supporto per l'opzione signal . |
v14.5.0 | Aggiunto in: v14.5.0 |
type
<string>listener
<Function> | <EventListener>options
<Object>once
<boolean> Quandotrue
, il listener viene rimosso automaticamente quando viene invocato per la prima volta. Predefinito:false
.passive
<boolean> Quandotrue
, serve come suggerimento che il listener non chiamerà il metodopreventDefault()
dell'oggettoEvent
. Predefinito:false
.capture
<boolean> Non utilizzato direttamente da Node.js. Aggiunto per completezza dell'API. Predefinito:false
.signal
<AbortSignal> Il listener verrà rimosso quando viene chiamato il metodoabort()
dell'oggetto AbortSignal specificato.
Aggiunge un nuovo gestore per l'evento type
. Qualsiasi listener
specificato viene aggiunto solo una volta per type
e per valore dell'opzione capture
.
Se l'opzione once
è true
, il listener
viene rimosso dopo la prossima volta che viene inviato un evento type
.
L'opzione capture
non viene utilizzata da Node.js in alcun modo funzionale se non per tracciare i listener di eventi registrati secondo le specifiche EventTarget
. Nello specifico, l'opzione capture
viene utilizzata come parte della chiave durante la registrazione di un listener
. Qualsiasi singolo listener
può essere aggiunto una volta con capture = false
e una volta con capture = true
.
function handler(event) {}
const target = new EventTarget();
target.addEventListener('foo', handler, { capture: true }); // first
target.addEventListener('foo', handler, { capture: false }); // second
// Rimuove la seconda istanza di handler
target.removeEventListener('foo', handler);
// Rimuove la prima istanza di handler
target.removeEventListener('foo', handler, { capture: true });
eventTarget.dispatchEvent(event)
Aggiunto in: v14.5.0
event
<Event>- Restituisce: <boolean>
true
se il valore dell'attributocancelable
dell'evento è false o il suo metodopreventDefault()
non è stato invocato, altrimentifalse
.
Inoltra l'event
all'elenco di gestori per event.type
.
I listener di eventi registrati vengono invocati sincronicamente nell'ordine in cui sono stati registrati.
eventTarget.removeEventListener(type, listener[, options])
Aggiunto in: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Rimuove il listener
dall'elenco dei gestori per l'type
dell'evento.
Classe: CustomEvent
[Cronologia]
Versione | Modifiche |
---|---|
v23.0.0 | Non più sperimentale. |
v22.1.0, v20.13.0 | CustomEvent è ora stabile. |
v19.0.0 | Non più dietro il flag CLI --experimental-global-customevent . |
v18.7.0, v16.17.0 | Aggiunto in: v18.7.0, v16.17.0 |
[Stabile: 2 - Stabile]
Stabile: 2 Stabilità: 2 - Stabile
- Estende: <Event>
L'oggetto CustomEvent
è un adattamento della CustomEvent
Web API. Le istanze vengono create internamente da Node.js.
event.detail
[Cronologia]
Versione | Modifiche |
---|---|
v22.1.0, v20.13.0 | CustomEvent è ora stabile. |
v18.7.0, v16.17.0 | Aggiunto in: v18.7.0, v16.17.0 |
[Stabile: 2 - Stabile]
Stabile: 2 Stabilità: 2 - Stabile
- Tipo: <any> Restituisce dati personalizzati passati durante l'inizializzazione.
Sola lettura.
Classe: NodeEventTarget
Aggiunto in: v14.5.0
- Estende: <EventTarget>
NodeEventTarget
è un'estensione specifica di Node.js per EventTarget
che emula un sottoinsieme dell'API EventEmitter
.
nodeEventTarget.addListener(type, listener)
Aggiunto in: v14.5.0
type
<stringa>listener
<Funzione> | <EventListener>- Restituisce: <EventTarget> questo
Estensione specifica di Node.js alla classe EventTarget
che emula l'equivalente API EventEmitter
. L'unica differenza tra addListener()
e addEventListener()
è che addListener()
restituirà un riferimento a EventTarget
.
nodeEventTarget.emit(type, arg)
Aggiunto in: v15.2.0
type
<stringa>arg
<qualsiasi>- Restituisce: <booleano>
true
se esistono listener di eventi registrati per iltype
, altrimentifalse
.
Estensione specifica di Node.js alla classe EventTarget
che invia l'arg
all'elenco di gestori per type
.
nodeEventTarget.eventNames()
Aggiunto in: v14.5.0
- Restituisce: <stringa[]>
Estensione specifica di Node.js alla classe EventTarget
che restituisce un array di nomi type
di eventi per i quali sono registrati i listener di eventi.
nodeEventTarget.listenerCount(type)
Aggiunto in: v14.5.0
Estensione specifica di Node.js alla classe EventTarget
che restituisce il numero di listener di eventi registrati per il type
.
nodeEventTarget.setMaxListeners(n)
Aggiunto in: v14.5.0
n
<number>
Estensione specifica di Node.js alla classe EventTarget
che imposta il numero massimo di listener di eventi come n
.
nodeEventTarget.getMaxListeners()
Aggiunto in: v14.5.0
- Restituisce: <number>
Estensione specifica di Node.js alla classe EventTarget
che restituisce il numero massimo di listener di eventi.
nodeEventTarget.off(type, listener[, options])
Aggiunto in: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Restituisce: <EventTarget> this
Alias specifico di Node.js per eventTarget.removeEventListener()
.
nodeEventTarget.on(type, listener)
Aggiunto in: v14.5.0
type
<string>listener
<Function> | <EventListener>- Restituisce: <EventTarget> this
Alias specifico di Node.js per eventTarget.addEventListener()
.
nodeEventTarget.once(type, listener)
Aggiunto in: v14.5.0
type
<string>listener
<Function> | <EventListener>- Restituisce: <EventTarget> this
Estensione specifica di Node.js alla classe EventTarget
che aggiunge un listener once
per il dato type
di evento. Questo è equivalente a chiamare on
con l'opzione once
impostata su true
.
nodeEventTarget.removeAllListeners([type])
Aggiunto in: v14.5.0
type
<stringa>- Restituisce: <EventTarget> this
Estensione specifica di Node.js alla classe EventTarget
. Se type
è specificato, rimuove tutti i listener registrati per type
, altrimenti rimuove tutti i listener registrati.
nodeEventTarget.removeListener(type, listener[, options])
Aggiunto in: v14.5.0
type
<stringa>listener
<Funzione> | <EventListener>options
<Oggetto>capture
<booleano>
Restituisce: <EventTarget> this
Estensione specifica di Node.js alla classe EventTarget
che rimuove il listener
per il dato type
. L'unica differenza tra removeListener()
e removeEventListener()
è che removeListener()
restituirà un riferimento a EventTarget
.