W3docs

Gestione degli errori JavaScript con try…catch

Gestisci gli errori JavaScript con try, catch, finally e throw. Copre l'oggetto Error, i tipi built-in, il catch binding opzionale, il rethrowing e i limiti asincroni. Esempi eseguibili.

Padroneggiare la gestione degli errori in JavaScript con Try...Catch

Gestire gli errori in modo efficace è fondamentale per costruire applicazioni robuste in JavaScript. Quando qualcosa va storto a runtime — una chiamata di rete fallisce, il JSON non è valido, una variabile è undefined — JavaScript lancia un'eccezione. Senza gestirla, quell'eccezione interrompe lo script. Questo articolo tratta l'istruzione try...catch, la clausola finally, l'operatore throw, l'oggetto Error e i suoi sottotipi built-in, il rethrowing e l'importante limitazione per cui il try...catch sincrono non può intercettare errori lanciati all'interno di callback asincrone.

Capire Try...Catch in JavaScript

L'istruzione try...catch è uno strumento per gestire le eccezioni — errori che si verificano durante l'esecuzione del programma. Permette di gestire queste eccezioni in modo controllato invece di lasciare che blocchino l'intero script.

Il meccanismo ha due blocchi:

  • try — il codice che potrebbe lanciare un'eccezione. JavaScript lo esegue normalmente.
  • catch (error) — viene eseguito solo se qualcosa nel blocco try lancia un'eccezione. Il valore lanciato viene passato come error.

Se non si verifica alcun errore, il blocco catch viene completamente saltato. Se si verifica un errore, l'esecuzione salta immediatamente a catch — il resto del blocco try non viene eseguito.

Sintassi di base di Try...Catch

Ecco un semplice esempio per illustrare la struttura di base di try...catch:


javascript— editable

In questo esempio, qualsiasi errore che si verifica nel blocco try viene intercettato dal blocco catch, dove può essere gestito senza causare il crash dello script.

Lanciare i propri errori con throw

L'operatore throw genera un'eccezione. È possibile lanciare qualsiasi valore, ma la convenzione — e l'unica cosa da fare in pratica — è lanciare un oggetto Error (o un'istanza di uno dei suoi sottotipi). In questo modo si ottengono automaticamente un utile message e una traccia stack.

javascript— editable

Evitare throw 'a string' o throw 42. Una string lanciata non ha message, namestack, quindi il codice che si aspetta un oggetto Error (come fa la maggior parte del codice) si comporterà in modo errato. Per errori specifici del dominio con campi aggiuntivi, definire una propria classe — vedere errori personalizzati, estendere Error.

L'oggetto Error

Quando si usa new Error(message), si ottiene un object con tre proprietà comunemente usate:

  • name — il tipo di errore, ad es. "Error", "TypeError", "SyntaxError".
  • message — la descrizione in linguaggio naturale passata al costruttore.
  • stack — una string con lo stack delle chiamate al momento della creazione dell'errore (non standard ma supportata da tutti i principali motori; ottima per il debug, non per il controllo del flusso).
javascript— editable

Tipi di errori built-in

JavaScript include diverse sottoclassi di Error che il motore lancia automaticamente. Conoscerle aiuta a scrivere logica catch più precisa:

TipoLanciato quando
SyntaxErrorIl codice o i dati sono malformati, ad es. JSON.parse() su JSON non valido.
TypeErrorUn valore non è del tipo atteso, ad es. chiamare una non-funzione o leggere una proprietà di undefined.
ReferenceErrorSi fa riferimento a una variabile inesistente.
RangeErrorUn valore è fuori dall'intervallo consentito, ad es. una lunghezza di array non valida.
URIErrordecodeURIComponent() o simili ricevono un URI malformato.
EvalErrorStorico; raramente lanciato dai motori moderni.

Ognuno di questi ha name impostato al proprio tipo, quindi è possibile ramificare con instanceof:

javascript— editable

Gestione di errori specifici

È possibile gestire anche tipi specifici di errori esaminando l'oggetto error:


javascript— editable

Questo esempio gestisce specificamente il SyntaxError che può verificarsi durante il parsing di JSON. Se l'errore intercettato è un'istanza di SyntaxError, viene gestito registrando un messaggio specifico. Se non lo è, l'errore viene rilanciato, potenzialmente per essere intercettato da un gestore di errori di livello superiore o per interrompere il programma, indicando uno scenario di errore non gestito.

Rethrowing degli errori

Un blocco catch intercetta tutti gli errori nel suo try, inclusi quelli che non si sa come gestire. Il pattern raccomandato è: esaminare l'errore, gestire i casi comprensibili e rilanciare tutto il resto in modo che si propaghi a un gestore esterno. Inghiottire errori sconosciuti silenziosamente nasconde bug reali.

javascript— editable

Catch binding opzionale

Se non si ha bisogno del valore dell'errore, è possibile omettere completamente il binding (ES2019+). Questo è utile quando tutto ciò che interessa è il semplice fatto che qualcosa sia fallito:

javascript— editable

Usare Finally

La clausola finally viene eseguita dopo i blocchi try e catch, indipendentemente dal fatto che sia stata lanciata o intercettata un'eccezione. È utile per liberare risorse o eseguire operazioni di pulizia, a prescindere dall'esito del try...catch:


javascript— editable

Questo garantisce che il messaggio "Finally block executed" venga registrato sia che si verifichi un errore sia che non si verifichi, dimostrando come finally possa essere usato per eseguire le azioni di pulizia necessarie.

Esempi reali con richieste API

Utilizzare la API JSONPlaceholder è un ottimo modo per esercitarsi nella gestione di dati reali in JavaScript, soprattutto quando si lavora con richieste asincrone e si gestiscono i potenziali errori che possono verificarsi durante queste operazioni. Ecco un paio di esempi reali che utilizzano la API JSONPlaceholder, che offre dati REST online fittizi con cui sperimentare per i test e la prototipazione.

Esempio 1: Recuperare post e gestire gli errori

In questo esempio, recuperiamo post dalla API JSONPlaceholder usando fetch e gestiamo i potenziali errori di rete o problemi con la risposta API:


javascript— editable

Questo script effettua una richiesta HTTP per recuperare un singolo elemento todo. Verifica se la risposta è positiva (ovvero stato HTTP 200-299). In caso contrario, lancia un errore con lo stato della risposta. Qualsiasi errore, sia da problemi di rete sia dall'istruzione throw, viene intercettato nel blocco catch e registrato. Il blocco finally viene eseguito indipendentemente dal risultato, assicurando che vengano eseguite tutte le operazioni di pulizia o finali necessarie.

Esempio 2: Inviare dati e gestire le eccezioni

Qui dimostriamo come inviare dati al server usando il metodo POST e gestire le eccezioni in modo appropriato:


javascript— editable

In questo script, stiamo inviando un nuovo post al server. La funzione fetch viene usata con il metodo POST, includendo header e un body con JSON serializzato. Se la risposta del server indica un errore (stato HTTP non 2xx), viene lanciato un errore, che viene poi intercettato e gestito nel blocco catch. Indipendentemente dal successo o dal fallimento, il blocco finally assicura che l'operazione sia contrassegnata come completata.

Esempio 3: Causare e gestire deliberatamente un errore

Questo esempio richiede intenzionalmente un ID utente che non esiste sulla API JSONPlaceholder, provocando un errore 404 Not Found, che intercetteremo e gestiremo.


javascript— editable

Come funziona questo esempio

  1. Endpoint API non valido: La funzione fetch viene chiamata con un URL che include un ID utente non valido (99999). Poiché JSONPlaceholder tipicamente non ha un utente a questo indice, l'API restituirà un errore 404.
  2. Verifica della validità della risposta: Il codice controlla se lo stato della risposta non è nell'intervallo di successo (200-299). Poiché l'ID utente non è valido, la risposta API sarà probabilmente 404, attivando la gestione degli errori nel controllo if (!response.ok).
  3. Lancio dell'errore: Poiché la risposta non è OK, viene lanciato un errore con il messaggio che include lo stato HTTP, che in questo caso indicherà un errore 404 Not Found.
  4. Blocco Catch: Il blocco catch intercetta l'errore lanciato e registra un messaggio specifico usando console.log. Questo fornisce un feedback chiaro su cosa è andato storto.
  5. Blocco Finally: Questo blocco viene utilizzato per la pulizia o le istruzioni finali, indicando il completamento del tentativo, indipendentemente dall'esito.

Perché Try...Catch non può intercettare errori nelle callback asincrone

Questa è la trappola più comune con try...catch. L'istruzione è sincrona: intercetta solo gli errori lanciati mentre il blocco try è attualmente in esecuzione. Quando si pianifica una callback con setTimeout, un event listener, o una promise non attesa con await, la callback viene eseguita in seguito — dopo che il try...catch ha già terminato e lo stack delle chiamate è vuoto. A quel punto non c'è nessun try circostante per intercettare nulla.

javascript— editable

Per gestire l'errore, il try...catch deve trovarsi all'interno della callback, dove l'errore viene effettivamente lanciato:

javascript— editable

La stessa regola spiega perché try...catch funziona con async/await ma non con promise senza await. await mette in pausa la funzione e la riprende nello stesso flusso logico, quindi una promise rifiutata emerge come errore lanciato che il try può intercettare. Una promise che non si attende con await si risolve in modo indipendente e aggira completamente il try circostante — è necessario usare .catch() invece.

javascript— editable

Per una copertura più approfondita della gestione degli errori asincroni, vedere Gestione degli errori con le promise e async/await.

Conclusione

Una gestione efficace degli errori in JavaScript è fondamentale per sviluppare applicazioni di alta qualità e resilienti. Usare try...catch permette di gestire in modo controllato gli errori sincroni e i rifiuti con await, mantenendo il controllo sul flusso dell'applicazione. Lanciare oggetti Error (mai string bare), ramificare sui tipi built-in come TypeError e SyntaxError, rilanciare ciò che non si riesce a gestire, e ricordare il limite asincrono: gli errori nelle callback e nelle promise non attese con await richiedono la propria gestione.

Argomenti correlati

Esercitazione

Pratica
Qual è lo scopo dell'istruzione try/catch in JavaScript?
Qual è lo scopo dell'istruzione try/catch in JavaScript?
Was this page helpful?