Promise, async/await e la fetch API con una timeline dell'event loop passo per passo e 15 esempi che puoi modificare ed eseguire: JSON, form, errori, richieste parallele, AbortController e retry.
Una promise rappresenta un risultato che arriverà più tardi. Le funzioni async restituiscono promise, e await mette in pausa quella funzione finché una non si risolve. fetch(url) restituisce una promise di una Response: controlla response.ok, poi fai await response.json(). Racchiudi gli await in try e catch, usa Promise.all per le richieste parallele e AbortController per annullare.
Lo schema che serve alla maggior parte delle pagine
Parti dalla timeline per capire perché il codice dopo un await può essere eseguito prima di esso. Poi modifica un esempio qualsiasi e si riesegue all'istante. Le richieste qui usano URL data: o server simulati, quindi nulla lascia il tuo browser.
Nessuna in quello che possono fare: async/await è costruito sopra le promise. Una funzione async restituisce sempre una promise, e await ne estrae il valore. Si legge come normale codice passo per passo, il che rende più facile gestire gli errori con try e catch.
fetch considera qualsiasi risposta HTTP una richiesta riuscita, perché il server ha risposto. Va in rejection solo per errori di rete o per una richiesta annullata. Controlla tu response.ok o response.status.
Le callback delle promise finiscono nella coda dei microtask, che viene svuotata completamente dopo lo script corrente. La callback di un timer è un task, che aspetta il giro successivo dell'event loop.
Crea un AbortController, passa controller.signal nelle opzioni di fetch e chiama controller.abort(). La promise di fetch va in rejection con un errore chiamato AbortError.
Sì, all'interno dei moduli JavaScript (script type="module" o qualsiasi modulo ES passato da un bundler). Negli script classici, racchiudi il codice in una funzione async.
Prima vengono eseguite le righe sincrone, poi ogni callback di promise in coda (microtask), poi il timer (un task). Cambia l'ordine ed eseguilo di nuovo.
Una promise si risolve una sola volta: resolve fornisce un valore, reject fornisce un errore. then e catch vengono eseguiti dopo, mai subito.
await mette in pausa solo la funzione async in cui si trova. La riga dopo la chiamata a main() viene eseguita prima che main finisca.
Dentro una funzione async un await in rejection lancia un errore, quindi i normali try e catch funzionano. finally è il posto giusto per nascondere uno spinner.
fetch restituisce una Response; .json() legge e interpreta il body, ed è un secondo await. Questo esempio usa un URL data: così funziona offline.
fetch va in rejection solo quando la richiesta non può proprio essere fatta (offline, bloccata, URL errato). Un 404 o un 500 si risolve normalmente con ok impostato a false, quindi controllalo sempre.
FormData legge ogni campo con un nome. Qui la richiesta viene costruita ma non inviata, e il suo body viene stampato così vedi esattamente cosa riceverebbe un server.
Invia JSON serializzandolo e impostando tu l'header Content-Type; fetch non fa nessuna delle due cose per gli oggetti semplici.
Quale helper delle promise usare
Fare await di una chiamata alla volta somma le attese. Avviarle tutte e fare await di Promise.all aspetta solo quanto la più lenta.
Promise.all va in rejection appena una fallisce. allSettled aspetta tutte e ti dice quali hanno funzionato, il che è adatto a dashboard con widget indipendenti.
Lanciare centinaia di richieste insieme può far scattare i rate limit. Questo piccolo pool ne tiene al massimo tre in corso.
Passa controller.signal a fetch e chiama abort() per fermarla. La promise va in rejection con un AbortError, che di solito ignori.
AbortSignal.timeout(ms) crea un signal che si interrompe da solo. Con fetch il nome dell'errore è TimeoutError, così puoi distinguerlo da un annullamento dell'utente.
Riprova solo gli errori che possono passare, come un timeout o un 503, e aspetta di più ogni volta così un server in difficoltà può riprendersi.
Aspetta una pausa nella digitazione e annulla la richiesta precedente quando ne parte una nuova, così una vecchia risposta lenta non può mai sovrascriverne una più recente.
Hai una risposta da leggere? Incollala nel
Call stack
Microtask
Coda dei task
Console
Passo {i} di {n}.
Indietro
Passo successivo
Pausa
Avvia
Reimposta
Inizia gratis · Nessuna carta di credito richiesta