Federico Lelli / SchoolNode.js & Express
LEZIONE 13 · HTTP e runtime

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 con new, è un oggetto con i propri listener.
on, once, emit e off
on registra un listener; once lo registra per una sola esecuzione; emit emette; off rimuove 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.

Torna all’indice ↑

Materiali didattici curati e rielaborati da Federico Lelli. Le fonti e i riferimenti specifici sono indicati nei materiali disponibili.