La Fetch API ha rivoluzionato il modo in cui interagiamo con le risorse di rete, mandando definitivamente in pensione il vecchio oggetto XMLHttpRequest (XHR). Integrata nativamente nei browser moderni e in Node.js (dalla versione 18+), questa API basata sulle Promises offre una sintassi pulita, potente e facilmente leggibile per gestire il flusso di dati asincrono.
Effettuare una Richiesta GET di base
Il metodo GET è il più comune per recuperare dati da un'endpoint. Con Fetch, l'operazione è immediata. Tuttavia, è fondamentale implementare un controllo sullo stato della risposta per evitare bug silenti.
// Recupero dati semplice
const response = await fetch('https://api.example.com/users');
const users = await response.json();
console.log(users);
// Implementazione con gestione errori professionale
async function fetchUsers() {
const response = await fetch('https://api.example.com/users');
// Verifica se la risposta è andata a buon fine (status 200-299)
if (!response.ok) {
throw new Error(`Errore HTTP: ${response.status}`);
}
return response.json();
}
Nota bene: A differenza di altre librerie come Axios, la Fetch API non rigetta la Promise in caso di errori HTTP (come 404 o 500). La Promise viene rifiutata solo se si verifica un errore di rete o se il server non è raggiungibile.
Inviare Dati: POST, PUT e DELETE
Per creare o aggiornare risorse sul server, dobbiamo configurare l'oggetto delle opzioni, specificando il metodo, gli header e il corpo della richiesta (body).
const response = await fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer IL_TUO_TOKEN',
},
body: JSON.stringify({
nome: 'Mario Rossi',
email: '[email protected]',
}),
});
const nuovoUtente = await response.json();
await fetch('https://api.example.com/users/42', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nome: 'Mario Rossi Aggiornato' }),
});
await fetch('https://api.example.com/users/42', {
method: 'DELETE',
headers: { 'Authorization': 'Bearer IL_TUO_TOKEN' },
});
Gestione dei Diversi Tipi di Risposta
Non tutte le API restituiscono JSON. La Fetch API mette a disposizione diversi metodi per interpretare il corpo della risposta in base alle necessità del tuo progetto.
const response = await fetch(url);
// Parsing come oggetto JSON
const data = await response.json();
// Parsing come testo semplice
const testo = await response.text();
// Dati binari (utili per immagini o file)
const blob = await response.blob();
// ArrayBuffer (dati binari grezzi)
const buffer = await response.arrayBuffer();
// Accesso ai metadati
console.log(response.status); // es: 200
console.log(response.ok); // true se status tra 200-299
console.log(response.headers.get('Content-Type'));
Utilizzo di AbortController per il Timeout
Spesso è necessario annullare una richiesta se impiega troppo tempo o se l'utente cambia pagina. Ecco come gestire il timeout in modo efficace.
const controller = new AbortController();
const signal = controller.signal;
// Impostiamo un timeout di 6 secondi
const timeoutId = setTimeout(() => controller.abort(), 6000);
try {
const res = await fetch('https://api.example.com/data', { signal });
clearTimeout(timeoutId);
const data = await res.json();
} catch (err) {
if (err.name === 'AbortError') {
console.warn('Richiesta annullata per timeout');
} else {
console.error('Errore imprevisto:', err);
}
}
Caricamento File con FormData
Per inviare file (come immagini o documenti), non bisogna convertire i dati in JSON. Si utilizza l'oggetto FormData, e il browser gestirà automaticamente i boundary del multipart/form-data.
const form = new FormData();
form.append('file', fileInput.files[0]);
form.append('userId', '12345');
// NOTA: Non impostare manualmente il Content-Type!
const response = await fetch('/api/upload', {
method: 'POST',
body: form,
});
Creazione di un Client API Riutilizzabile
Per evitare di ripetere sempre lo stesso codice, è buona norma creare una classe wrapper che centralizzi la logica delle chiamate.
class ApiService {
constructor(baseUrl) {
this.baseUrl = baseUrl;
}
async call(endpoint, options = {}) {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers: {
'Content-Type': 'application/json',
...options.headers,
},
});
if (!response.ok) throw new Error('Errore API');
return response.json();
}
get(path) { return this.call(path); }
post(path, body) {
return this.call(path, { method: 'POST', body: JSON.stringify(body) });
}
}
const api = new ApiService('https://api.test.com');
const data = await api.get('/v1/products');
Errori Comuni e Best Practices
- Dimenticare
response.ok: Ricorda che fetch non "fallisce" se il server risponde con un errore 404 o 500. - Parsing multiplo: Il body di una risposta può essere letto una sola volta (es. non puoi chiamare
.json()e poi.text()). - Gestione degli Header CORS: Assicurati che il server accetti le richieste cross-origin se chiami API su domini diversi.
- Stringify del Body: Ricorda sempre di usare
JSON.stringify()quando invii oggetti JSON nel body.
Ottimizza il tuo Flusso di Lavoro
Utilizza i nostri strumenti gratuiti per formattare i tuoi dati API e codificare i parametri URL in un click.