Tutorial sull’API di recupero JavaScript: GET, POST, gestione degli errori e timeout

  1. Home
  2. Blog
  3. Sviluppo software

Sviluppo software

Tutorial sull’API di recupero JavaScript: GET, POST, gestione degli errori e timeout

Fetch è il modo integrato per chiamare le API da JavaScript, ma ha una sorpresa che cattura quasi tutti. Impara a inviare richieste, gestire ogni tipo di errore e creare un piccolo aiutante che puoi riutilizzare.

9 min di lettura
Tutorial sull'API di recupero JavaScript: GET, POST, gestione degli errori e timeout

Punti chiave

  • fetch() restituisce una promessa per a Response e la lettura del corpo richiede un secondo await.
  • Errori HTTP come 404 e 500 non rifiutare, quindi controlla sempre response.ok.
  • Per inviare JSON, utilizzare JSON.stringify e impostare l’intestazione Content-Type.
  • Fetch non ha un’opzione di timeout predefinita, quindi usa AbortSignal.timeout().

La maggior parte delle app Web moderne comunica continuamente con un server. L’API JavaScript Fetch è il modo standard per farlo ed è integrata nei browser e in Node.js 18 e versioni successive, quindi non c’è nulla da installare.

L’utilizzo di base richiede due righe, ma molti tutorial si fermano qui e tralasciano la parte che causa veri bug: la gestione degli errori. Abbiamo testato gli esempi in questa guida su un piccolo server locale su Node.js 24 e l’output mostrato proviene da quell’esecuzione. example.com nel codice indica la tua API. Se le promesse sono nuove per te, inizia con Spiegazione delle promesse JavaScript.

Cos’è l’API di recupero?

Fetch è un’interfaccia basata su promesse per effettuare richieste HTTP. Ha sostituito il vecchio, basato sul callback XMLHttpRequest, e molti progetti ora lo utilizzano invece di aggiungere una libreria per semplici chiamate.

Caratteristica Recupera Axios (biblioteca)
Installazione Costruito dentro Aggiunto come dipendenza
Corpo JSON Stringilo tu stesso Automatico
Analizza la risposta JSON Chiama response.json() Automatico
Gli errori HTTP vengono rifiutati? No Sì, per impostazione predefinita
Timeout Attraverso AbortSignal Un’opzione timeout.

Una richiesta GET

Fetch effettua una richiesta GET per impostazione predefinita. Ci sono due passaggi e ognuno richiede await: prima arrivano le intestazioni della risposta e poi si legge il corpo.

const response = await fetch("https://example.com/users/1");
const user = await response.json();

console.log(user);

// { id: 1, name: 'Asha' }

I due passaggi esistono perché il corpo può essere grande e arrivare dopo le intestazioni. In uno script del browser, il livello superiore await necessita di un modulo, quindi di solito lo inserirai all’interno di una funzione async. Consulta la nostra guida JavaScript async/await.

L’oggetto Risposta

Prima di leggere il corpo, puoi esaminare la risposta:

console.log(response.status, response.ok, response.headers.get("content-type"));

// 200 true application/json
Proprietà o metodo Ti dà
response.ok true per gli stati da 200 a 299
response.status Il codice di stato, ad esempio 404
response.headers.get(name) Un’intestazione di risposta
response.json() Il corpo è stato analizzato come JSON
response.text() Il corpo come una corda
response.blob() Dati binari, ad esempio un’immagine

Un corpo può essere letto una sola volta. Chiamare json() una seconda volta non è riuscito nel nostro test:

await res.json();
await res.json();

// TypeError: Body is unusable: Body has already been read

Se hai bisogno di leggerlo due volte, chiama prima response.clone().

La grande sorpresa: un 404 non lancia

Questa è la cosa più importante in questo articolo. Abbiamo richiesto un utente che non esiste:

const res = await fetch("https://example.com/users/999");
console.log(res.status, res.ok);

// 404 false

Non è stata lanciata alcuna eccezione. Per quanto riguarda il fetch la richiesta ha funzionato: il server è stato raggiunto e ha risposto. La promessa viene rifiutata solo quando non arriva alcuna risposta utilizzabile, come nel caso di un guasto della rete. Quindi un codice come questo ha un bug nascosto:

try {
  const res = await fetch(url);
  const data = await res.json();   // may be an error payload
  showUser(data);                  // runs anyway for 404 and 500
} catch (error) {
  showError();                     // does not run for 404 or 500
}

Controlla il nostro trucco sui codici di stato HTTP per vedere il significato di ciascun codice.

Un aiuto riutilizzabile

Non ripetere il controllo ovunque. Avvolgilo una volta:

async function getJson(url, options) {
  const response = await fetch(url, options);
  if (!response.ok) {
    throw new Error(`Request failed with status ${response.status}`);
  }
  return response.json();
}

try {
  await getJson("https://example.com/users/999");
} catch (error) {
  console.log("caught:", error.message);
}

// caught: Request failed with status 404

Ora gli errori HTTP e gli errori di rete finiscono entrambi nello stesso catch. Vale la pena avere questa piccola funzione in ogni progetto. Una versione reale potrebbe anche leggere un messaggio di errore dal corpo della risposta e gestire una risposta 204 No Content, che non ha JSON da analizzare.

POSTARE dati JSON

Passa un oggetto opzioni come secondo argomento. Per JSON, devi fare due cose tu stesso: convertire i dati in una stringa e impostare l’intestazione.

const created = await getJson("https://example.com/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Ben" }),
});

console.log(created);

// { id: 2, name: 'Ben', type: 'application/json' }

Il nostro server di test ha risposto al tipo di contenuto ricevuto, confermando l’arrivo dell’intestazione. Dimenticare quell’intestazione è una causa comune di errori del server confusi, perché molti framework analizzano JSON solo quando viene dichiarato. Per caricare un modulo o file, passa un oggetto FormData come corpo e non imposta Content-Type, poiché il browser stesso deve aggiungere un valore limite.

Altri metodi e opzioni

Opzione Esempio Scopo
metodo "PUT", "PATCH", "DELETE" Il metodo HTTP
intestazioni { Autorizzazione: "Portatore ..." } Richiedi intestazioni
corpo JSON.stringify(data) Il corpo della richiesta
segnale AbortSignal.timeout(5000) Annullamento
credenziali "includere" Invio di cookie multiorigine
cache "nessun negozio" Comportamento della cache del browser

Scegliere tra REST e altri stili API? Il nostro confronto tra REST e GraphQL mostra come il recupero si adatta a ciascuno.

Stringhe di query

Non creare stringhe di query unendo il testo, perché i caratteri speciali le interromperebbero. URLSearchParams gestisce la codifica per te:

const params = new URLSearchParams({ q: "red shoes", page: 2 });
console.log(params.toString());

// q=red+shoes&page=2

await getJson(`https://example.com/search?${params}`);

// { q: 'red shoes', page: '2' }

Il server ha ricevuto red shoes correttamente, con lo spazio ripristinato.

Timeout e annullamento

Fetch attenderà a lungo su un server lento a meno che tu non dica diversamente. AbortSignal.timeout() stabilisce un limite. Il nostro endpoint di test ha impiegato due secondi, contro un limite di 200 millisecondi:

try {
  await fetch("https://example.com/slow", { signal: AbortSignal.timeout(200) });
} catch (error) {
  console.log(error.name);
}

// TimeoutError

Per annullare manualmente, ad esempio quando un utente lascia una pagina o digita un nuovo termine di ricerca, utilizza un AbortController:

const controller = new AbortController();
const pending = fetch("https://example.com/slow", { signal: controller.signal });

controller.abort();

try {
  await pending;
} catch (error) {
  console.log(error.name);
}

// AbortError

Per eseguire più richieste contemporaneamente, utilizzare Promise.all, che è molto più veloce che attenderle una alla volta:

const [user, search] = await Promise.all([
  getJson("https://example.com/users/1"),
  getJson("https://example.com/search?q=a&page=1"),
]);

Ogni tipo di fallimento

Ecco come appariva ogni fallimento nella nostra corsa, insieme a come distinguerli:

Situazione Cosa succede Come rilevarlo
Il server restituisce 404 o 500 La promessa si realizza response.ok è falso
Impossibile raggiungere il server Rifiuta con TypeError catturare
Timeout raggiunto Rifiuta con TimeoutError error.name
Annullato manualmente Rifiuta con AbortError error.name
Il corpo non è un JSON valido json() rifiuta con SyntaxError catturare

Quest’ultima riga è comune nella produzione. Un proxy che restituisce un 502 invia spesso una pagina di errore HTML. Lo abbiamo riprodotto e res.json() ha lanciato un SyntaxError. Controllare response.ok prima dell’analisi significa segnalare il problema reale piuttosto che un errore di analisi confuso.

Suggerimento: testa di proposito questi percorsi di errore. Gli strumenti per sviluppatori del browser possono simulare l’essere offline e gli strumenti di test possono simulare una risposta 500. La nostra guida Test API con Postman copre il controllo del lato API.

CORS e credenziali

In un browser, una richiesta da un’origine a un’altra è soggetta a CORS, le regole di condivisione delle risorse tra origini. Se vedi un errore che menziona Access-Control-Allow-Origin, la correzione appartiene al server, che deve consentire il tuo sito. Nel tuo JavaScript, l’errore viene visualizzato solo come generico TypeError, quindi cerca il motivo effettivo nella console del browser. Node.js non applica CORS, quindi una richiesta che funziona in uno script può comunque fallire nel browser.

Per impostazione predefinita, i browser non inviano cookie su richieste multiorigine. Imposta credentials: "include" se ne hai bisogno e assicurati che il server lo consenta. Non inserire mai chiavi API segrete nel JavaScript del browser, poiché chiunque può leggerle. Tienili sul tuo server.

Errori comuni

  • Non controllare response.ok. Le risposte agli errori vengono trattate come riuscite.
  • Dimenticare il secondo await. response.json() restituisce anche una promessa.
  • Dimenticare JSON.stringify. Passare un oggetto mentre il corpo invia [object Object].
  • Impostazione Content-Type con FormData. Questo rompe il confine, quindi lascialo fuori.
  • Non esiste timeout. Una richiesta sospesa può lasciare lo spinner di una pagina in esecuzione per un tempo indefinito.
  • Analisi JSON per una risposta vuota. Un 204 non ha corpo e json() genererà un’eccezione.

Considerazioni finali

Il recupero è semplice una volta ricordata la sua regola principale: una risposta non è la stessa cosa di un successo. Copia il piccolo helper nel tuo progetto, aggiungi un timeout e testa i tuoi percorsi di errore. Come passaggio successivo, crea una piccola pagina che carichi i dati da un’API, mostri un messaggio di errore chiaro e consenta all’utente di annullare una ricerca lenta.

Domande frequenti

Il recupero genera un errore su un 404?

No. il recupero rifiuta solo quando non viene ricevuta alcuna risposta, ad esempio in caso di errore di rete. Per gli errori HTTP, controlla tu stesso Response.ok o Response.status.

Come posso inviare JSON con il recupero?

Imposta il metodo su POST, aggiungi un’intestazione Content-Type di application/json e passa i dati tramite JSON.stringify come corpo.

Perché ho bisogno di due attese con il recupero?

Il primo si risolve una volta arrivate le intestazioni di risposta. Il secondo attende che il corpo venga scaricato e analizzato, cosa che può avvenire in seguito.

Come posso impostare un timeout durante il recupero?

Passa segnale: AbortSignal.timeout(5000) nelle opzioni. La richiesta viene quindi rifiutata con un TimeoutError se impiega più di quel numero di millisecondi.

Il recupero è disponibile in Node.js?

SÌ. Fetch è disponibile a livello globale in Node.js 18 e versioni successive. Le versioni precedenti necessitano di un pacchetto, sebbene le regole CORS si applichino solo nei browser.

Continua a imparare

Lavora con Stack Quora

Hai bisogno di aiuto con test, WordPress o SEO?

Aiutiamo i team a fornire software migliore e a far crescere i loro siti. Raccontaci a cosa stai lavorando e ti suggeriremo chiaramente il prossimo passo.

Continua a leggere

Altre guide su test, intelligenza artificiale e sviluppo moderno

Ti è piaciuto questo articolo? Scegli un argomento e passa direttamente ai nostri tutorial più recenti.

Intelligenza artificiale

Spiegazione delle allucinazioni dell'intelligenza artificiale: perché i modelli linguistici inventano le cose e come ridurle

Spiegazione delle allucinazioni dell'intelligenza artificiale: cosa sono, perché i modelli linguistici le producono, tipi comuni, come ridurle con b…

Leggi l'articolo →
DevOps

Spiegazione delle variabili d'ambiente: file .env, segreti e configurazione eseguiti correttamente

Variabili d'ambiente spiegate con esempi Python che abbiamo eseguito: lettura e impostazione, perché ogni valore è una stringa, file .env, ereditari…

Leggi l'articolo →
Sviluppo software

Spiegazione della limitazione della velocità API: algoritmi, intestazioni e gestione degli errori 429

La limitazione della velocità dell'API spiegata con una simulazione che abbiamo eseguito: bucket di token, finestra fissa, finestra scorrevole, risp…

Leggi l'articolo →
Automazione dei test

Derisione in Python: unittest.mock, patch e gli errori che fanno mentire i test

Mocking in Python con unittest.mock, testato: Mock e return_value, side_effect, patch dove viene utilizzato un nome, specifiche e autospec, date moc…

Leggi l'articolo →
Test del software

Spiegazione della copertura del codice: copertura di linea o di filiale e cosa significa realmente il 100%.

Copertura del codice spiegata con una vera esecuzione di cover.py: copertura di linea, ramo e condizione, lettura di un rapporto, perché la copertur…

Leggi l'articolo →
Database e SQL

DELETE vs TRUNCATE vs DROP in SQL: differenze, rollback e quando utilizzarli

DELETE vs TRUNCATE vs DROP spiegato con SQL testato: cosa rimuove, rollback, trigger, reimpostazione dell'identità, velocità e come differiscono Pos…

Leggi l'articolo →
Database e SQL

Spiegazione delle visualizzazioni SQL: crea, utilizza ed evita le insidie, con esempi

Viste SQL spiegate con le query che abbiamo eseguito: creazione di una vista, risultati in tempo reale, nascondere colonne, prestazioni, viste aggio…

Leggi l'articolo →
Sviluppo software

Interfaccia TypeScript e tipo: differenze reali, testate con il compilatore

Interfaccia TypeScript vs tipo, verificata con il vero compilatore: cosa possono fare entrambi, cosa può fare solo uno, fusione delle dichiarazioni,…

Leggi l'articolo →
Sviluppo software

Spiegazione di Python *args e **kwargs: funzioni flessibili con esempi chiari

Python *args e **kwargs spiegati con il codice che abbiamo eseguito: compressione e decompressione, ordine dei parametri, argomenti solo per parole …

Leggi l'articolo →
Sviluppo software

Funzioni Lambda Python: sintassi, usi reali e quando non usarli

Funzioni lambda Python spiegate con il codice che abbiamo eseguito: sintassi, ordinamento con chiave, mappa e filtro, chiusure, trap dell'associazio…

Leggi l'articolo →
Intelligenza artificiale

Cosa sono gli agenti AI? Come funzionano, con un semplice ciclo di agenti che puoi eseguire

Cosa sono gli agenti IA? Una semplice guida al ciclo dell'agente, agli strumenti, alla memoria e ai guardrail, con un piccolo ciclo Python che abbia…

Leggi l'articolo →
DevOps

Monitoraggio vs osservabilità: la vera differenza, con log, metriche e tracce

Spiegazione del monitoraggio e dell'osservabilità: errori noti e sconosciuti, log, metriche e tracce, una procedura dettagliata sugli incidenti di p…

Leggi l'articolo →
DevOps

Volumi Docker e montaggi di associazione: mantenere i dati del contenitore nel modo giusto

Volumi Docker e montaggi di collegamento spiegati: perché i dati del contenitore scompaiono, volumi denominati, montaggi di collegamento, tmpfs, ese…

Leggi l'articolo →
Automazione dei test

TDD vs BDD: differenze chiave, una caratteristica costruita in entrambi i modi e quando utilizzarli ciascuno

TDD vs BDD spiegato con una funzione di sconto costruita in entrambi i modi: refactoring rosso-verde con il codice che abbiamo eseguito, scenari "Da…

Leggi l'articolo →
Test del software

Test di accettazione da parte dell'utente (UAT): processo, lista di controllo ed esempi reali

Spiegazione del test di accettazione dell'utente: chi lo esegue, in cosa differisce dal QA, un processo in sette fasi, un modello di test case UAT, …

Leggi l'articolo →
Database e SQL

Spiegazione dei valori SQL NULL: IS NULL, COALESCE, NULLIF e le trappole da evitare

Valori SQL NULL spiegati con le query che abbiamo eseguito: logica a tre valori, IS NULL, COALESCE, NULLIF, come aggregazioni, join e ordinamento tr…

Leggi l'articolo →
Database e SQL

Istruzione SQL CASE WHEN: sintassi, esempi reali ed errori comuni

SQL CASE WHEN spiegato con le query che abbiamo eseguito: moduli semplici e cercati, ordine delle condizioni, pivot con SUM, trucchi COUNT, ordiname…

Leggi l'articolo →
Sviluppo software

Cos'è il JWT? Token Web JSON spiegati con un esempio funzionante

Cos'è il JWT? Spiegazione dei token Web JSON: le tre parti, un token creato e manomesso nel codice che abbiamo eseguito, JWT e sessioni, archiviazio…

Leggi l'articolo →
Sviluppo software

Spiegazione del loop di eventi JavaScript: stack di chiamate, microtask e timer con esempi

Il ciclo di eventi JavaScript spiegato con il codice che abbiamo eseguito: stack di chiamate, code di attività e microtask, perché setTimeout 0 non …

Leggi l'articolo →
Sviluppo software

Spiegazione dei generatori Python e del rendimento: risparmia memoria con esempi reali

Generatori Python e rendimento spiegati con il codice che abbiamo eseguito: come vengono messi in pausa e ripresi, misurato il risparmio di memoria,…

Leggi l'articolo →
Intelligenza artificiale

Cosa sono gli incorporamenti? I vettori e la somiglianza del coseno spiegati semplicemente

Cosa sono gli incorporamenti? Una guida in linguaggio semplice ai vettori, alla similarità del coseno e alla ricerca semantica, con un piccolo esemp…

Leggi l'articolo →
DevOps

Distribuzione blu-verde rispetto a quella canaria: differenze, compromessi e come scegliere

Spiegazione della distribuzione blu-verde e canary: come funziona ciascuna, costi, rischi e rollback, bucket utente stabile che abbiamo testato, mig…

Leggi l'articolo →
Automazione dei test

Test instabili: quali sono le cause e come risolverli definitivamente

Test instabili spiegati con demo che abbiamo eseguito: le cause principali, come confermarne e diagnosticarne uno, soluzioni adeguate per tempistich…

Leggi l'articolo →
Test del software

Test di carico e test di stress: differenze, metriche ed esempi k6

Spiegazione del test di carico e dello stress test: cosa dimostra ciascuno, test di picco e di assorbimento, le metriche che contano, perché le medi…

Leggi l'articolo →
Test del software

Caso di test e scenario di test: differenze chiave, esempi e quando utilizzarli

Spiegazione del caso di test e dello scenario di test: definizioni chiare, una tabella affiancata, una funzione di reimpostazione della password pre…

Leggi l'articolo →
Database e SQL

Ottimizzazione delle query SQL: leggi i piani di esecuzione e correggi query lente, con tempistiche

Ottimizzazione delle query SQL testata su un milione di righe: leggi i piani di esecuzione, aggiungi gli indici corretti, correggi filtri non aggior…

Leggi l'articolo →
Database e SQL

SQL UNION vs UNION ALL: differenze, esempi e prestazioni testate

SQL UNION vs UNION ALL spiegati con le query che abbiamo eseguito: duplicati, regole seguite da entrambi, un vero bug di dati, prestazioni misurate,…

Leggi l'articolo →
Sviluppo software

Tutorial sull'API di recupero JavaScript: GET, POST, gestione degli errori e timeout

Un tutorial sull'API JavaScript Fetch testato su un server locale: GET e POST, perché 404 non genera eccezioni, un helper riutilizzabile, stringhe d…

Leggi l'articolo →
Sviluppo software

Gestione dei file Python: lettura, scrittura, CSV, JSON e pathlib con esempi

Gestione dei file Python spiegata con il codice che abbiamo eseguito: modalità aperte, con, lettura di file di grandi dimensioni, CSV, JSON, pathlib…

Leggi l'articolo →
Sviluppo software

Git merge vs rebase: differenze, esempi e quando usare ciascuno

Git merge vs rebase spiegato con output reale del log, una tabella di confronto, la regola d'oro del rebase e un flusso di lavoro sicuro per i team.

Leggi l'articolo →
Sviluppo software

List comprehension in Python: sintassi, esempi e quando evitarla

List comprehension in Python spiegata: sintassi, filtri, if-else, cicli annidati, tempi misurati e i casi in cui un normale ciclo for è meglio.

Leggi l'articolo →
Database e SQL

SQL JOIN spiegati con esempi (Inner, Left, Right, Full)

Capisci i JOIN SQL passo dopo passo con tabelle e query di esempio: INNER, LEFT, RIGHT, FULL, CROSS e SELF, con errori comuni e consigli sulle prest…

Leggi l'articolo →