Illustrazione di error handling in JavaScript con try…catch e async/await, con finestra di codice e simboli di errore e successo

Error Handling in JavaScript: Guida a Try…Catch con Async/Await

Se c’è una certezza nello sviluppo software, è questa: qualcosa andrà storto. Un’API che non risponde, un JSON malformato o una connessione internet che cade proprio mentre l’utente preme “Invia”.

In JavaScript, gestire questi casi è vitale: se non lo fai, la tua applicazione può bloccarsi lasciando l’utente davanti a una schermata bianca. In questa guida vediamo come gestire gli errori in modo moderno ed elegante con try catch async await, migliorando leggibilità e robustezza del codice.


Il problema: codice asincrono e gestione degli errori

Prima di async/await, gestivamo le operazioni asincrone con le Promise. Se qualcosa andava storto, concatenavamo un .catch() alla fine della catena. Funzionava, ma con logiche complesse il codice tendeva a diventare verboso e difficile da seguire.

Con async/await possiamo scrivere codice asincrono che sembra sincrono e utilizzare uno dei costrutti più solidi della programmazione per gestire gli errori: try...catch. Questo approccio rende più chiaro “dove può succedere l’errore” e “cosa facciamo quando succede”.

La struttura base: Try, Catch e Finally

La sintassi è semplice: “proviamo” (try) a eseguire un blocco di codice; se qualcosa va storto, lo “catturiamo” (catch). Il blocco finally è opzionale ma utilissimo: viene eseguito sempre, sia in caso di successo sia in caso di errore.

Esempio rapido: chiamata API + parsing JSON, con gestione errori e cleanup.

Analisi del flusso

  1. Try: se una riga lancia un errore (o un await riceve una Promise rigettata), l’esecuzione salta subito al catch.
  2. Catch: riceve l’errore. Qui gestisci il fallimento (messaggio utente, fallback, retry, logging).
  3. Finally: pulizia sempre garantita (nascondere spinner, chiudere connessioni, ripristinare stato UI).

Best practice: gestire errori HTTP con Fetch (la trappola più comune)

Un errore comune è pensare che catch intercetti qualsiasi problema con fetch. In realtà, fetch() va in catch soprattutto per errori di rete (DNS, offline, CORS bloccato dal browser, ecc.). Se invece il server risponde con 404 o 500, la Promise si risolve comunque: sta a te controllare response.ok.

Ecco una versione robusta che gestisce sia errori di rete sia errori HTTP, mantenendo il codice chiaro con try catch async await:

Tip UX: nel catch restituisci un valore “safe” (es. array vuoto) se ha senso per il tuo caso d’uso, così eviti errori a cascata nell’interfaccia.


Cosa NON fare: anti-pattern comuni

1) Il catch silenzioso

Non lasciare mai il catch vuoto. Ignorare un errore è spesso peggio che far crashare l’app: rende impossibile il debugging e nasconde bug reali in produzione.

2) Mischiare .then() con try/catch nella stessa funzione

Se usi async/await, sii coerente: non mescolare .then().catch() e try...catch nella stessa funzione. La leggibilità cala e diventa più difficile capire il flusso degli errori.

3) Lanciare errori “generici” senza contesto

Quando fai throw new Error(...), includi dettagli utili (endpoint, status, operazione) e logga in modo strutturato. In produzione, la differenza tra “Errore generico” e “GET /api/prodotti 500” è enorme.


Conclusione

Usare try...catch con async/await rende la gestione degli errori asincroni lineare e comprensibile. Con due accorgimenti (controllo di response.ok e finally per la pulizia) puoi rendere la tua app molto più resiliente.

Ricorda: un buon sviluppatore non è chi scrive codice che non fallisce mai, ma chi scrive codice che sa fallire bene quando succede.

Risorse autorevoli MDN: try…catch e MDN: Fetch API.