Introduzione
Quando si lavora con la Fetch API, uno dei passaggi più importanti è gestire le richieste in modo leggibile e manutenibile. In JavaScript moderno, la combinazione di Fetch API e async/await è spesso la soluzione migliore per scrivere codice chiaro, lineare e facile da debuggare.
Se hai già usato Promise e i relativi metodi come .then() e .catch(), sai che funzionano bene, ma possono diventare meno immediati quando la logica cresce. Con async/await, invece, il codice assomiglia molto a un flusso sincrono: questo rende più semplice leggere il comportamento di una chiamata HTTP, gestire gli errori e organizzare il codice in funzioni riutilizzabili.
In questo tutorial vedremo un caso pratico: recuperare una lista di prodotti da un’API pubblica, mostrare i risultati e gestire correttamente gli errori. L’obiettivo non è solo “far funzionare” la richiesta, ma scrivere una struttura robusta e adatta a un progetto reale.
Codice completo
/**
* Esempio pratico:
* recuperiamo una lista di prodotti da un´API pubblica
* usando fetch + async/await.
*/
const API_URL = ´https://fakestoreapi.com/products?limit=5´;
async function caricaProdotti() {
try {
// 1) Avvio della richiesta HTTP
const response = await fetch(API_URL);
// 2) Controllo dello stato HTTP
if (!response.ok) {
throw new Error(`Errore HTTP: ${response.status} ${response.statusText}`);
}
// 3) Parsing del JSON
const prodotti = await response.json();
// 4) Uso dei dati
console.log(´Prodotti ricevuti:´, prodotti);
// Esempio di rendering semplice in pagina
renderProdotti(prodotti);
} catch (error) {
console.error(´Impossibile caricare i prodotti:´, error.message);
mostraErrore(´Non è stato possibile caricare i prodotti. Riprova più tardi.´);
}
}
function renderProdotti(prodotti) {
const container = document.querySelector(´#app´);
if (!container) {
console.warn(´Container #app non trovato´);
return;
}
container.innerHTML = `
Lista prodotti
${prodotti
.map(
(prodotto) => `
-
${prodotto.title}
Prezzo: €${prodotto.price}
`
)
.join(´´)}
`;
}
function mostraErrore(messaggio) {
const container = document.querySelector(´#app´);
if (!container) {
console.warn(´Container #app non trovato´);
return;
}
container.innerHTML = `
${messaggio}
`;
}
// Avvio
caricaProdotti(); Spiegazione
Il punto chiave di questo approccio è la parola chiave async. Quando una funzione è dichiarata come async, JavaScript sa che al suo interno potremo usare await. Questo significa che possiamo “attendere” il risultato di una promessa senza dover scrivere una catena lunga di .then().
1. La richiesta con fetch
La chiamata fetch(API_URL) restituisce una promessa. Quando usiamo await, il codice si ferma in quel punto finché la risposta non arriva. Il vantaggio è che il flusso resta molto leggibile:
- invio la richiesta;
- controllo la risposta;
- estraggo i dati JSON;
- li uso nell’interfaccia.
2. Il controllo di response.ok
Un errore molto comune è pensare che fetch fallisca automaticamente per qualsiasi problema HTTP. In realtà, fetch rifiuta la promessa soprattutto in caso di errori di rete o problemi di connessione. Se il server risponde con un codice 404 o 500, la promessa viene comunque risolta, ma response.ok sarà false.
Per questo motivo è buona pratica verificare sempre:
if (!response.ok) {
throw new Error(`Errore HTTP: ${response.status}`);
} In questo modo trasformiamo una risposta HTTP non valida in un errore gestibile nel blocco catch.
3. Parsing del JSON
Una volta verificata la risposta, usiamo await response.json() per convertire il corpo della risposta in un oggetto JavaScript. Anche questo metodo restituisce una promessa, quindi è perfetto da usare con await.
Se l’API restituisce una struttura dati complessa, puoi poi elaborarla con funzioni dedicate, filtri o mappe, mantenendo il codice ordinato.
4. Gestione degli errori con try/catch
Il blocco try/catch è uno dei vantaggi più importanti di async/await. Tutte le operazioni potenzialmente fallibili vengono inserite nel try, mentre nel catch puoi centralizzare il trattamento degli errori.
Questo rende il codice più semplice da mantenere rispetto a catene di promesse con più punti di intercettazione degli errori.
5. Separare logica e presentazione
Nel codice di esempio abbiamo separato la funzione che carica i dati (caricaProdotti) da quella che li mostra a schermo (renderProdotti). Questa è una buona pratica importante: la funzione che fa la richiesta HTTP non dovrebbe occuparsi troppo della UI, e viceversa.
In progetti reali, questa separazione aiuta a:
- riutilizzare la logica di fetch in più punti;
- testare più facilmente il codice;
- ridurre la complessità delle funzioni.
Best practice
- Controlla sempre response.ok prima di leggere il corpo della risposta.
- Usa try/catch per centralizzare la gestione degli errori.
- Separa la logica di rete dalla UI per rendere il codice più pulito e testabile.
- Evita funzioni troppo grandi: una funzione dovrebbe avere una responsabilità chiara.
- Gestisci gli stati dell’interfaccia: caricamento, successo ed errore dovrebbero essere visibili all’utente.
- Valuta timeout e cancellazione se la richiesta può restare bloccata troppo a lungo.
- Non dare per scontato il formato dei dati: verifica sempre che la struttura ricevuta sia quella attesa.
Un’altra buona abitudine è creare una piccola funzione di utilità per le richieste HTTP, così da evitare di ripetere sempre gli stessi controlli in tutto il progetto. Ad esempio, puoi costruire un wrapper attorno a fetch che gestisca in modo uniforme errori, parsing e validazione base.
Riepilogo
Usare Fetch API con async/await è uno dei modi più efficaci per scrivere codice asincrono chiaro in JavaScript. Rispetto alle catene di promesse, il flusso è più leggibile e più vicino al ragionamento naturale: fai la richiesta, controlli la risposta, leggi i dati e li usi.
I concetti fondamentali da ricordare sono:
- fetch restituisce una promessa;
- await semplifica l’attesa del risultato;
- response.ok va controllato sempre;
- try/catch è essenziale per gli errori;
- separare richiesta e rendering migliora la qualità del codice.
Se stai costruendo frontend moderni o semplici applicazioni vanilla JavaScript, padroneggiare async/await con fetch è una competenza fondamentale. Ti permette di scrivere codice più pulito, più robusto e più facile da estendere nel tempo.
Approfondisci con risorse ufficiali
- MDN Web Docs - Fetch API: documentazione completa e aggiornata sulla Fetch API.
- MDN Web Docs - async function: guida ufficiale alle funzioni asincrone in JavaScript.
- MDN Web Docs - Promise: approfondimento sul funzionamento delle promesse.
- WHATWG Fetch Standard: specifica tecnica della Fetch API per chi vuole andare più in profondità.
Se vuoi, nel prossimo passo posso scrivere anche un tutorial dedicato a Fetch API con async/await e loading state in una UI reale, oppure a creare un wrapper fetch riutilizzabile per progetti più grandi.
