Eventi
[Stabile: 2 - Stabile]
Stabile: 2 Stabilità: 2 - Stabile
Codice sorgente: lib/events.js
Gran parte dell'API core di Node.js è costruita attorno a un'architettura idiomatica asincrona guidata dagli eventi in cui determinati tipi di oggetti (chiamati "emettitori") emettono eventi denominati che causano la chiamata di oggetti Function
("listener").
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 sono disponibili dati da leggere.
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 formato 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. Qualsiasi valore restituito dai listener chiamati viene ignorato e scartato.
L'esempio seguente mostra una semplice istanza di 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('si è verificato un evento!')
})
myEmitter.emit('event')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('si è verificato un evento!')
})
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 in modo da 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)
// Stampa:
// 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)
// Stampa:
// 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 Freccia ES6 come listener, tuttavia, in tal caso, 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)
// Stampa: 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)
// Stampa: 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. Ciò 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 avviene 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 avviene in modo asincrono')
})
})
myEmitter.emit('event', 'a', 'b')
Gestione degli eventi una sola volta
Quando un listener viene registrato utilizzando il metodo eventEmitter.on()
, tale listener viene invocato ogni volta che viene emesso l'evento specificato.
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')
// Stampa: 1
myEmitter.emit('event')
// Stampa: 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')
// Stampa: 1
myEmitter.emit('event')
// Stampa: 2
Utilizzando il metodo eventEmitter.once()
, è possibile registrare un listener che viene chiamato al massimo una volta per un determinato 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')
// Stampa: 1
myEmitter.emit('event')
// Ignorato
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')
// Stampa: 1
myEmitter.emit('event')
// Ignorato
Eventi di errore
Quando si verifica un errore all'interno di un'istanza di EventEmitter
, l'azione tipica è che venga emesso 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 termina.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// Lancia un'eccezione e blocca 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 blocca Node.js
Per proteggersi dal blocco del processo Node.js, è possibile utilizzare il modulo domain
. (Si noti, tuttavia, che il modulo node:domain
è deprecato.)
Come buona pratica, i listener dovrebbero 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! si è verificato un errore')
})
myEmitter.emit('error', new Error('whoops!'))
// Stampa: whoops! si è verificato un errore
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
console.error('whoops! si è verificato un errore')
})
myEmitter.emit('error', new Error('whoops!'))
// Stampa: whoops! si è verificato un errore
È possibile monitorare gli eventi 'error'
senza consumare l'errore emesso installando un listener utilizzando 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 comunque un'eccezione e blocca 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 comunque un'eccezione e blocca Node.js
Catturare i rifiuti delle promise
L'utilizzo di funzioni async
con i gestori di eventi è problematico, perché può portare a un rifiuto non gestito in caso di eccezione generata:
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 cambiano 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 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
Impostando events.captureRejections = true
si 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 | Cambiamenti |
---|---|
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 le seguenti opzioni:
captureRejections
<boolean> Abilita l'acquisizione automatica del rifiuto della promise. Predefinito:false
.
Evento: 'newListener'
Aggiunto in: v0.1.26
eventName
<stringa> | <simbolo> Il nome dell'evento per il quale si sta ascoltandolistener
<Funzione> La funzione di gestione 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: eventuali listener aggiuntivi registrati con lo stesso name
all'interno del callback 'newListener'
vengono inseriti prima del listener che è in fase di aggiunta.
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
// Esegui questo solo una volta per 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()
// Esegui questo solo una volta per 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 usando .once() , l'argomento listener ora restituisce la funzione listener originale. |
v0.9.3 | Aggiunto in: v0.9.3 |
eventName
<stringa> | <simbolo> Il nome dell'eventolistener
<Funzione> La funzione di gestione dell'evento
L'evento 'removeListener'
viene emesso dopo che il listener
viene rimosso.
emitter.addListener(eventName, listener)
Aggiunto in: v0.1.26
eventName
<stringa> | <simbolo>listener
<Funzione>
Alias per emitter.on(eventName, listener)
.
emitter.emit(eventName[, ...args])
Aggiunto in: v0.1.26
eventName
<stringa> | <simbolo>...args
<qualsiasi>- Restituisce: <booleano>
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 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)
// Stampa:
// [
// [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)
// Stampa:
// [
// [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 che elenca gli eventi per i quali l'emitter 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())
// Stampa: [ '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())
// Stampa: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
Aggiunto in: v1.0.0
- Restituisce: <integer>
Restituisce il valore massimo corrente dei listener per l'EventEmitter
che è impostato da emitter.setMaxListeners(n)
o per impostazione predefinita a events.defaultMaxListeners
.
emitter.listenerCount(eventName[, listener])
[Cronologia]
Versione | Cambiamenti |
---|---|
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 per l'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 allegati usando .once() ora restituisce i listener originali invece delle funzioni wrapper. |
v0.1.26 | Aggiunto in: v0.1.26 |
eventName
<stringa> | <simbolo>- Restituisce: <Funzione[]>
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 verificare se il listener
è già stato aggiunto. Chiamate multiple che passano la stessa combinazione di eventName
e listener
comporteranno l'aggiunta e la chiamata del listener
più volte.
server.on('connection', stream => {
console.log('qualcuno si è connesso!')
})
Restituisce un riferimento a EventEmitter
, in modo che le chiamate possano essere concatenate.
Per impostazione predefinita, i listener di eventi vengono richiamati nell'ordine in cui sono stati aggiunti. Il metodo emitter.prependListener()
può essere utilizzato in alternativa per aggiungere il listener di eventi 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 all'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 in 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 dei listener per l'evento chiamato eventName
. Non vengono effettuati 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 all'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 viene attivato eventName
, 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 EventEmitter
è stata creata da un altro componente o modulo (ad es. 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 singolo listener è stato aggiunto più volte all'array dei listener per lo specifico eventName
, allora removeListener()
deve essere chiamato più volte per rimuovere ogni 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 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 dei listener interno al momento dell'emissione [callbackA, callbackB]
myEmitter.emit('event')
// Stampa:
// A
// B
// callbackB è stato rimosso.
// Array dei 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 dei listener interno al momento dell'emissione [callbackA, callbackB]
myEmitter.emit('event')
// Stampa:
// A
// B
// callbackB è stato rimosso.
// Array dei listener interno [callbackA]
myEmitter.emit('event')
// Stampa:
// A
Poiché i listener vengono gestiti utilizzando un array interno, la chiamata a questo cambierà gli indici di posizione di qualsiasi listener registrato dopo il listener che viene rimosso. Ciò non influenzerà l'ordine in cui vengono chiamati i listener, ma significa che qualsiasi copia dell'array dei listener restituita 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
visualizzeranno un avviso se vengono aggiunti più di 10
listener per un particolare evento. Questa è un'impostazione predefinita 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 a EventEmitter
, in modo che le chiamate possano essere concatenate.
emitter.rawListeners(eventName)
Aggiunto in: v9.4.0
eventName
<string> | <symbol>- Restituisce: <Function[]>
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 collegato sopra
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// Registra "log once" nella console e non scollegare l'evento `once`
logFnWrapper.listener()
// Registra "log once" nella console e rimuove il listener
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// Restituirà un nuovo Array con una singola funzione collegata 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 collegato sopra
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// Registra "log once" nella console e non scollegare l'evento `once`
logFnWrapper.listener()
// Registra "log once" nella console e rimuove il listener
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// Restituirà un nuovo Array con una singola funzione collegata 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 |
Il metodo Symbol.for('nodejs.rejection')
viene chiamato nel caso in cui si verifichi un rifiuto di una promise quando viene emesso un evento e captureRejections
è abilitato sull'emitter. È 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('il rifiuto è avvenuto per', event, 'con', err, ...args)
this.destroy(err)
}
destroy(err) {
// Demolire la risorsa qui.
}
}
const { EventEmitter, captureRejectionSymbol } = require('node:events')
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true })
}
[captureRejectionSymbol](err, event, ...args) {
console.log('il rifiuto è avvenuto per', event, 'con', err, ...args)
this.destroy(err)
}
destroy(err) {
// Demolire la risorsa qui.
}
}
events.defaultMaxListeners
Aggiunto in: v0.11.2
Per impostazione predefinita, è possibile registrare un massimo di 10
listener per qualsiasi singolo evento. Questo limite può essere modificato per 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 interessa tutte le istanze di EventEmitter
, comprese quelle create prima della modifica. 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 visualizzerà 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 cose
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 cose
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0))
})
Il flag della riga di comando --trace-warnings
può essere utilizzato per visualizzare la stack trace di tali avvisi.
L'avviso emesso può essere controllato con process.on('warning')
e avrà le proprietà aggiuntive emitter
, type
e count
, riferendosi rispettivamente all'istanza dell'emitter 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 usato per installare un listener solo per monitorare gli eventi 'error'
. I listener installati usando questo simbolo vengono chiamati prima che vengano chiamati i normali listener 'error'
.
Installare un listener usando questo simbolo non cambia il comportamento una volta che viene emesso un evento 'error'
. Pertanto, il processo si arresterà comunque se non è installato nessun listener 'error'
normale.
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 gli EventEmitter
questo si comporta esattamente come chiamare .listeners
sull'emettitore.
Per gli EventTarget
questo è l'unico modo per ottenere i listener degli eventi per l'event target. Questo è utile per il debug e per scopi diagnostici.
import { getEventListeners, EventEmitter } from 'node:events'
{
const ee = new EventEmitter()
const listener = () => console.log('Gli eventi sono divertenti')
ee.on('foo', listener)
console.log(getEventListeners(ee, 'foo')) // [ [Function: listener] ]
}
{
const et = new EventTarget()
const listener = () => console.log('Gli eventi sono divertenti')
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('Gli eventi sono divertenti')
ee.on('foo', listener)
console.log(getEventListeners(ee, 'foo')) // [ [Function: listener] ]
}
{
const et = new EventTarget()
const listener = () => console.log('Gli eventi sono divertenti')
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
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 dell'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('si è verificato un errore', 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('si è verificato un errore', 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, viene trattato come qualsiasi altro tipo di evento senza 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('errore', err.message))
ee.emit('error', new Error('boom'))
// Stampa: 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('errore', err.message))
ee.emit('error', new Error('boom'))
// Stampa: ok boom
Un <AbortSignal> può essere utilizzato per annullare l'attesa dell'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('evento emesso!')
} catch (error) {
if (error.name === 'AbortError') {
console.error("L'attesa dell'evento è stata annullata!")
} else {
console.error('Si è verificato un errore', error.message)
}
}
}
foo(ee, 'foo', ac.signal)
ac.abort() // Stampa: L'attesa dell'evento è stata annullata!
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('evento emesso!')
} catch (error) {
if (error.name === 'AbortError') {
console.error("L'attesa dell'evento è stata annullata!")
} else {
console.error('Si è verificato un errore', error.message)
}
}
}
foo(ee, 'foo', ac.signal)
ac.abort() // Stampa: L'attesa dell'evento è stata annullata!
Attesa di più eventi emessi su process.nextTick()
C'è un caso limite che vale la pena notare quando si usa 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 di 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 attenderle, quindi diventa possibile usare 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>
Modifica 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 rifiuto personalizzato.
events.listenerCount(emitter, eventName)
Aggiunto in: v0.9.12
Deprecato a partire da: v3.2.0
[Stabile: 0 - Deprecato]
Stabile: 0 Stabilità: 0 - Deprecato: Usa invece emitter.listenerCount()
.
emitter
<EventEmitter> L'emitter da interrogareeventName
<string> | <symbol> Il nome dell'evento
Un metodo di classe che restituisce il numero di listener per il dato eventName
registrato sul dato emitter
.
import { EventEmitter, listenerCount } from 'node:events'
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// Stampa: 2
const { EventEmitter, listenerCount } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// Stampa: 2
events.on(emitter, eventName[, options])
[Cronologia]
Versione | Modifiche |
---|---|
v22.0.0, v20.13.0 | Supporto per 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> | <simbolo> Il nome dell'evento in ascoltooptions
<Oggetto>signal
<AbortSignal> Può essere utilizzato per annullare gli eventi in attesa.close
- <string[]> Nomi degli eventi che termineranno l'iterazione.highWaterMark
- <intero> Predefinito:Number.MAX_SAFE_INTEGER
La soglia massima. L'emettitore viene messo in pausa ogni volta che la dimensione degli eventi in fase di buffering è superiore ad essa. Supportato solo su emettitori che implementano i metodipause()
eresume()
.lowWaterMark
- <intero> Predefinito:1
La soglia minima. L'emettitore viene ripreso ogni volta che la dimensione degli eventi in fase di buffering è inferiore ad essa. Supportato solo su 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 e
// elabora un evento alla volta (anche con await). Non utilizzare
// se è richiesta l'esecuzione simultanea.
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 e
// elabora un evento alla volta (anche con await). Non utilizzare
// se è richiesta l'esecuzione simultanea.
console.log(event) // stampa ['bar'] [42]
}
// Irraggiungibile qui
})()
Restituisce un AsyncIterator
che itera sugli eventi eventName
. Genera un'eccezione se l'EventEmitter
emette 'error'
. Rimuove tutti i listener all'uscita dal ciclo. 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 e
// elabora un evento alla volta (anche con await). Non utilizzare
// se è richiesta l'esecuzione simultanea.
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 e
// elabora un evento alla volta (anche con await). Non utilizzare
// se è richiesta l'esecuzione simultanea.
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 viene specificato nessuno,n
viene impostato come 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 sola volta l'evento abort
sul signal
fornito.
Ascoltare l'evento abort
sui segnali di interruzione non è sicuro e potrebbe portare a perdite di risorse poiché un'altra terza parte con il segnale può chiamare e.stopImmediatePropagation()
. Sfortunatamente, Node.js non può cambiarlo perché violerebbe lo standard web. Inoltre, l'API originale rende facile dimenticare di rimuovere i listener.
Questa API consente di utilizzare in modo sicuro 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 annullato più facilmente.
const { addAbortListener } = require('node:events')
function example(signal) {
let disposable
try {
signal.addEventListener('abort', e => e.stopImmediatePropagation())
disposable = addAbortListener(signal, e => {
// Esegui qualcosa quando il segnale viene interrotto.
})
} 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 => {
// Esegui qualcosa quando il segnale viene interrotto.
})
} 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 di 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 di 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([opzioni])
opzioni
<Object>captureRejections
<boolean> Abilita l'acquisizione automatica del rifiuto delle promesse](/it/api/events#capture-rejections-of-promises). 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 sottoposto a garbage collection. Di solito non è necessario impostarlo (anche seemitDestroy
viene chiamato manualmente), a meno che l'asyncId
della risorsa non venga recuperato e venga chiamato l'API sensibileemitDestroy
con esso. Quando è impostato sufalse
, la chiamataemitDestroy
sulla 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: L'oggetto <AsyncResource> sottostante.
L'oggetto AsyncResource
restituito ha una proprietà aggiuntiva eventEmitter
che fornisce un riferimento a questo EventEmitterAsyncResource
.
eventemitterasyncresource.emitDestroy()
Chiama tutti gli hook destroy
. Questo dovrebbe essere chiamato una sola volta. Verrà generato un errore se viene chiamato più di una volta. Questo deve essere chiamato manualmente. Se la risorsa viene lasciata alla garbage collection, gli hook destroy
non verranno mai chiamati.
eventemitterasyncresource.triggerAsyncId
- Tipo: <numero> Lo stesso
triggerAsyncId
che viene passato al costruttoreAsyncResource
.
API EventTarget
e Event
[Cronologia]
Versione | Cambiamenti |
---|---|
v16.0.0 | Gestione degli errori di EventTarget modificata. |
v15.4.0 | Non più sperimentale. |
v15.0.0 | Le classi EventTarget e Event sono ora disponibili come globali. |
v14.5.0 | Aggiunto in: v14.5.0 |
Gli oggetti EventTarget
e 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 vs. EventTarget
del DOM
Ci sono due differenze fondamentali tra EventTarget
di Node.js e EventTarget
Web API:
NodeEventTarget
vs. 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 di gestione viene richiamata con l'argomento event
passato alla funzione eventTarget.dispatchEvent()
.
Le funzioni asincrone possono essere utilizzate come listener di eventi. Se una funzione di gestione asincrona rifiuta, il rifiuto viene acquisito e gestito come descritto in gestione degli errori di EventTarget
.
Un errore generato da una funzione di gestione non impedisce la chiamata degli altri gestori.
Il valore di ritorno di una funzione di gestione viene ignorato.
I gestori vengono sempre richiamati nell'ordine in cui sono stati aggiunti.
Le funzioni di gestione 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 di EventTarget
Quando un listener di eventi registrato lancia un'eccezione (o restituisce una Promise che viene rifiutata), per impostazione predefinita l'errore viene trattato come un'eccezione non catturata in process.nextTick()
. Ciò significa che le eccezioni non catturate in EventTarget
termineranno il processo Node.js per impostazione predefinita.
Lanciare un'eccezione all'interno di un listener di eventi non impedirà l'invocazione degli altri gestori 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 Node.js. Qualsiasi codice che si basa sull'evento process.on('error')
dovrebbe essere allineato con il nuovo comportamento.
Classe: Event
[Cronologia]
Versione | Modifiche |
---|---|
v15.0.0 | La classe Event è ora disponibile tramite l'oggetto globale. |
v14.5.0 | Aggiunto in: v14.5.0 |
L'oggetto Event
è un adattamento della Event
Web API. Le istanze vengono create internamente da Node.js.
event.bubbles
Aggiunto in: v14.5.0
- Tipo: <boolean> Restituisce sempre
false
.
Questo non viene utilizzato in Node.js ed è fornito esclusivamente per completezza.
event.cancelBubble
Aggiunto in: v14.5.0
[Stabile: 3 - Eredità]
Stabile: 3 Stabilità: 3 - Eredità: utilizzare event.stopPropagation()
invece.
- Tipo: <boolean>
Alias per event.stopPropagation()
se impostato su true
. Questo non viene utilizzato in Node.js ed è fornito esclusivamente per completezza.
event.cancelable
Aggiunto 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 viene utilizzato in Node.js ed è fornito solo per completezza.
event.composedPath()
Aggiunto in: v14.5.0
Restituisce un array contenente l'attuale EventTarget
come unica voce o vuoto se l'evento non viene distribuito. Questo non viene utilizzato in Node.js ed è fornito solo 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
ed è stato chiamato event.preventDefault()
.
event.eventPhase
Aggiunto in: v14.5.0
- Tipo: <number> Restituisce
0
mentre un evento non viene distribuito,2
mentre viene distribuito.
Questo non viene utilizzato in Node.js ed è fornito solo 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 obsoleto e gli utenti non dovrebbero usarlo affatto.
Ridondante con i costruttori di eventi e incapace di impostare composed
. Questo non viene utilizzato in Node.js ed è fornito solo 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: Usa event.defaultPrevented
invece.
- Tipo: <boolean> Vero 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 per completezza.
event.srcElement
Aggiunto in: v14.5.0
[Stabile: 3 - Legacy]
Stabile: 3 Stabilità: 3 - Legacy: Usa event.target
invece.
- 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 è completo.
event.stopPropagation()
Aggiunto in: v14.5.0
Questo non viene utilizzato in Node.js ed è fornito puramente per 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 in cui l'oggetto Event
è stato creato.
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 | aggiungi 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 la prima volta. Predefinito:false
.passive
<boolean> Quandotrue
, funge da suggerimento che il listener non chiamerà il metodopreventDefault()
dell'oggettoEvent
. Predefinito:false
.capture
<boolean> Non direttamente utilizzato 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 handler per l'evento type
. Qualsiasi listener
specificato viene aggiunto una sola volta per type
e per valore dell'opzione capture
.
Se l'opzione once
è true
, il listener
viene rimosso dopo la successiva emissione di 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 la specifica EventTarget
. In particolare, l'opzione capture
viene utilizzata come parte della chiave quando si registra 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 }) // prima
target.addEventListener('foo', handler, { capture: false }) // seconda
// 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
.
Invia l'evento
all'elenco di gestori per event.type
.
Gli ascoltatori di eventi registrati vengono invocati in modo sincrono 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 di gestori per l'evento type
.
Classe: CustomEvent
[Storia]
Versione | Modifiche |
---|---|
v23.0.0 | Non più sperimentale. |
v22.1.0, v20.13.0 | CustomEvent è ora stabile. |
v19.0.0 | Non più nascosto 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
[Storia]
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 i dati personalizzati passati durante l'inizializzazione.
Sola lettura.
Classe: NodeEventTarget
Aggiunto in: v14.5.0
- Estende: <EventTarget>
NodeEventTarget
è un'estensione specifica di Node.js a EventTarget
che emula un sottoinsieme dell'API EventEmitter
.
nodeEventTarget.addListener(type, listener)
Aggiunto in: v14.5.0
type
<string>listener
<Function> | <EventListener>- Restituisce: <EventTarget> this
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
<string>arg
<any>- Restituisce: <boolean>
true
se esistono listener di eventi registrati pertype
, altrimentifalse
.
Estensione specifica di Node.js alla classe EventTarget
che distribuisce arg
alla lista di gestori per type
.
nodeEventTarget.eventNames()
Aggiunto in: v14.5.0
- Restituisce: <string[]>
Estensione specifica di Node.js alla classe EventTarget
che restituisce un array di nomi di type
di eventi per i quali sono registrati 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 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 evento type
. Questo equivale a chiamare on
con l'opzione once
impostata su true
.
nodeEventTarget.removeAllListeners([type])
Aggiunto in: v14.5.0
type
<string>- Restituisce: <EventTarget>
this
Estensione specifica di Node.js alla classe EventTarget
. Se viene specificato type
, rimuove tutti i listener registrati per type
, altrimenti rimuove tutti i listener registrati.
nodeEventTarget.removeListener(type, listener[, options])
Aggiunto in: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Restituisce: <EventTarget>
this
Estensione specifica di Node.js alla classe EventTarget
che rimuove il listener
per il type
fornito. L'unica differenza tra removeListener()
e removeEventListener()
è che removeListener()
restituirà un riferimento a EventTarget
.