EventEmitter e programmazione a eventi
Prima di iniziare: le parole della lezione
- Evento, emittente e listener
- Un evento è una notifica con un nome ed eventuali dati. L’emittente la produce; un listener è la funzione registrata per reagire.
- EventEmitter e istanza
EventEmitterè la classe di Node per notifiche a eventi. Un’istanza, creata connew, è un oggetto con i propri listener.- on, once, emit e off
onregistra un listener;oncelo registra per una sola esecuzione;emitemette;offrimuove un listener specifico.
EventEmitter fornisce un modello per emettere eventi e registrare ascoltatori. È utile per notifiche interne, strumenti e flussi applicativi.
// eventi.cjs
const { EventEmitter } = require('node:events');
const bus = new EventEmitter();
bus.on('utenteCreato', utente => console.log('Creato:', utente.nome));
bus.once('primoAccesso', () => console.log('Solo una volta'));
bus.emit('utenteCreato', { nome: 'Luca' });
bus.emit('primoAccesso');
bus.emit('primoAccesso'); // nessun secondo log
Attenzione: emit() invoca sincronamente gli ascoltatori registrati. EventEmitter non crea automaticamente code persistenti né rende le funzioni asincrone. Gestisci con cura gli eventi error.
Chi fa cosa, e perché
L’ordine conta: registra gli ascoltatori prima di emettere l’evento. Un normale EventEmitter non conserva un evento per chi si iscrive dopo. Gli argomenti passati dopo il nome in emit vengono consegnati ai listener nello stesso ordine.
La registrazione non chiama subito la funzione; emit chiama invece in modo sincrono gli ascoltatori già registrati. Se un listener avvia lavoro asincrono, quel lavoro ha la propria durata: l’emittente non aspetta automaticamente tutte le Promise. Il modello serve per disaccoppiare una notifica dalle reazioni, ma non garantisce consegna persistente fra processi.
Un altro esempio guidato
// ascoltatori.cjs — node ascoltatori.cjs
const { EventEmitter } = require('node:events');
const eventi = new EventEmitter();
function registra(id, totale) {
console.log(`Ordine ${id}: ${totale} euro`);
}
eventi.on('ordine', registra);
eventi.emit('ordine', 7, 25);
eventi.off('ordine', registra);
eventi.emit('ordine', 8, 30);
Come leggerlo e risultato atteso. Viene stampato solo l’ordine 7. Per rimuovere un listener serve il riferimento alla stessa funzione: una nuova arrow function, anche con lo stesso corpo, è un altro oggetto funzione. Nell’esempio iniziale il secondo primoAccesso non stampa nulla perché il listener era registrato con once.
Prova tu. Aggiungi due listener allo stesso evento e verifica l’ordine delle stampe; poi emetti prima di registrarli per osservare che l’evento non viene riprodotto.