Un'introduzione alla programmazione basata sugli eventi in Node.js
La potente architettura basata sugli eventi di Node è uno dei suoi maggiori vantaggi.
Punti chiave
- La programmazione basata sugli eventi è una buona scelta per le app interattive, in particolare le app GUI, poiché consente al codice di rispondere alle azioni dell'utente in qualsiasi ordine.
- La programmazione basata sugli eventi viene comunemente utilizzata nelle app Web, dove gli ascoltatori di eventi si attivano quando gli utenti interagiscono con il DOM.
- Implementare la programmazione basata sugli eventi in Node.js è semplice con la classe EventEmitter, che ti consente di creare eventi personalizzati e collegare ascoltatori di eventi per gestirli.
Quando si crea un'applicazione software, una decisione cruciale riguarda la selezione del paradigma appropriato per il codice.
La programmazione basata sugli eventi è una buona scelta per le app interattive che rispondono alle azioni dell'utente che possono verificarsi in qualsiasi ordine. È un paradigma più popolare con le app GUI che con i programmi a riga di comando o il codice di sistemi incorporati.
Cosa sono gli eventi?
Puoi considerare un evento come un'azione o un evento che il tuo codice può riconoscere e a cui può rispondere. Il sistema o un utente possono attivare un evento e il codice solitamente registrerà una funzione per gestirlo.
Un esempio di un evento di base è fare clic su un pulsante per eseguire un'azione particolare. L'atto di fare clic sul pulsante attiva un evento e la funzione che viene eseguita quando si verifica il clic è chiamata ascoltatore di eventi (o gestore).
Che cos'è la programmazione guidata dagli eventi?
La programmazione guidata dagli eventi è un paradigma di programmazione in cui il flusso di esecuzione di un’applicazione dipende da eventi che si verificano anziché essere strettamente sequenziali.
Questo paradigma viene utilizzato principalmente durante la creazione di interfacce utente e applicazioni in tempo reale, dove un evento come l'azione di un utente dovrebbe attivare un'azione nel sistema.
Il paradigma è molto popolare durante la creazione di app Web, in cui i listener di eventi si attivano quando gli utenti interagiscono con il Document Object Model (DOM).
L'immagine seguente mostra come funziona il flusso nella programmazione basata sugli eventi. Quando si verifica un evento, il canale degli eventi lo riceve e lo trasmette al listener appropriato per gestirlo:
Programmazione guidata dagli eventi in Node.js
Il loop di eventi JavaScript è uno dei concetti fondamentali alla base della natura asincrona del runtime Node.js. Un'architettura basata sugli eventi utilizza il modulo EventEmitter integrato per facilitare il flusso di esecuzione senza interruzioni.
Con la programmazione basata sugli eventi, Node.js ti consente di creare applicazioni lato server in grado di gestire l'interazione dell'utente, le operazioni di I/O e l'elaborazione dei dati in tempo reale. Ciò avviene in modo non bloccante, con conseguente miglioramento delle prestazioni e un'esperienza più fluida per l'utente.
Implementare la programmazione basata sugli eventi in Node.js è semplice quando si comprendono le nozioni di base sulla definizione, l'attivazione e la gestione degli eventi.
La classe EventEmitter
Con la classe EventEmitter in Node.js, puoi creare eventi personalizzati e collegare listener di eventi per gestirli. Per utilizzare la classe nel tuo codice, importala dal modulo events in questo modo:
// CommonJS
const { EventEmitter } = require("events")
// ES6
import { EventEmitter } from "events"
La classe e le relative funzioni membro saranno quindi disponibili per l'uso nell'applicazione. Per iniziare a emettere e gestire eventi, inizializza una nuova istanza della classe EventEmitter.
Per esempio:
const FoodEvents = new EventEmitter()
Questo crea un nuovo oggetto emettitore chiamato FoodEvents che può emettere eventi e registrare ascoltatori. La classe EventEmmitter fornisce tre metodi per ascoltare un evento: on, addListener e once.
Il metodo on è la funzione più basilare per aggiungere ascoltatori di eventi e addListener funziona esattamente allo stesso modo. Entrambi accettano il nome dell'evento e una funzione di callback come argomenti. Il callback è la funzione effettiva del gestore. Puoi utilizzare on e addListener in modo intercambiabile.
Ecco come gestisci un evento utilizzando il metodo on:
FoodEvents.on("cookie_ready", (data) => {
console.log("Cookie ready for packaging, data received: ", data);
})
Utilizzo di addListener come alternativa diretta a on:
FoodEvents.addListener("cookie_ready", (data) => {
console.log(
"Cookie will now be packaged and sent out, data received: ",
data
);
})
Entrambi questi esempi aggiungeranno la richiamata all'array di ascoltatori di eventi per l'evento cookie_ready. Se li usi entrambi, i loro callback verranno attivati in ordine.
Il metodo once registra un ascoltatore di eventi una tantum che viene eseguito la prossima volta che si attiva l'evento. Successivamente, il sistema lo rimuoverà dall'array di ascoltatori.
Ecco come utilizzare once per gestire un evento singolo:
FoodEvents.once("cookie_sent", (data) => {
console.log("Cookie is sent out, data received: ", data);
})
In questo caso, l'emettitore ascolterà l'evento cookie_sent solo una volta e rimuoverà il gestore dopo l'esecuzione.
Tutti e tre i metodi restituiscono l'emettitore, quindi puoi concatenare le chiamate a uno qualsiasi di essi.
Non dimenticare che, affinché un ascoltatore possa gestire un evento, l'applicazione deve emettere quell'evento ad un certo punto. Ecco del codice di esempio per emettere l'evento cookie_ready utilizzando il metodo emit:
function bakeCookie() {
console.log("Cookie is baking, almost ready...")
setTimeout(() => {
FoodEvents.emit("cookie_ready", { flavor: "vanilla cookie" })
}, 3000)
}
bakeCookie()
Quando esegui questo codice che stampa un avviso nella console che il cookie sta cuocendo, attende 3 secondi ed emette l'evento cookie_ready, otterrai un output come l'immagine seguente:
Ciò dimostra come vengono eseguiti i listener di eventi nell'ordine in cui li registri.
La classe EventEmitter fornisce più metodi, tra cui:
- removeListener: rimuove un'istanza di un ascoltatore dall'array di ascoltatori di eventi. A questo scopo è disponibile anche il metodo off.
- prependListener: anche questo metodo registra un ascoltatore ma, invece di aggiungerlo alla fine dell'array degli ascoltatori, lo aggiunge all'inizio. Verrà quindi eseguito prima di qualsiasi altro ascoltatore che potresti aver già registrato.
- prependOnceListener: funziona proprio come prependListener, ma il listener viene eseguito solo una volta, come nel caso di once.
- removeAllListeners: questa funzione rimuove tutti gli ascoltatori registrati per un evento con nome specifico o tutti gli ascoltatori se non gli passi alcun argomento.
- ascoltatori: restituisce un array di ascoltatori del nome dell'evento che gli passi come argomento.
- eventNames: puoi utilizzare questa funzione per ottenere tutti i nomi degli eventi per i quali hai già registrato un ascoltatore.
- setMaxListeners: Node.js genera un avviso per impostazione predefinita quando registri più di 10 ascoltatori per un evento, per evitare perdite di memoria. È possibile modificare questo valore predefinito utilizzando setMaxListeners. Puoi anche controllare questo valore utilizzando getMaxListeners.
Il pacchetto events fornisce funzionalità complete per la programmazione basata sugli eventi in Node.js.
Quali sono alcune best practice per la programmazione basata sugli eventi?
Ogni approccio alla programmazione ha i suoi compromessi e ignorare le migliori pratiche può avere effetti negativi sulla tua applicazione. Di seguito sono riportate alcune best practice da considerare quando si creano applicazioni basate su eventi:
- Utilizza nomi concisi e descrittivi per gli eventi per consentire una codebase pulita e gestibile.
- Adottare buone pratiche di gestione e registrazione degli errori, per consentire un facile debug degli errori.
- Evita l'inferno dei callback (nidificazione di più callback) durante la scrittura di listener di eventi. Utilizza invece le promesse JavaScript.
- Non creare troppi ascoltatori per un evento. Considera invece la possibilità di dividere gli eventi e di concatenarli.
Crea applicazioni con la giusta architettura
Una regola generale che si applica alla creazione di software è prendere decisioni appropriate in materia di architettura e progettazione. Quando segui l’approccio sbagliato alla creazione di un’applicazione, alla fine ne dovrai affrontare le conseguenze.
La programmazione basata sugli eventi è un paradigma che può avere un impatto significativo sull’architettura e sulle prestazioni di un’applicazione. Ogni volta che la tua applicazione, o parte di essa, dipende dagli eventi per funzionare, dovresti considerare la programmazione guidata dagli eventi.