JavaScript — Asincrono

Callback · Promise · async/await · Fetch API · 2026 · Marco Consiglio
Volta Institute · Napoli
A.A. 2026
⏱️ Il problema: operazioni che richiedono tempo
Alcune operazioni non producono un risultato immediato: scaricare dati da un server, leggere un file, aspettare una risposta API. JavaScript è single-threaded (esegue un'istruzione alla volta) ma non può permettersi di "bloccarsi" in attesa — altrimenti l'intera pagina si congelerebbe. Il codice asincrono risolve questo: avvia un'operazione lunga, continua a fare altro, e reagisce quando il risultato è pronto.
// Codice SINCRONO: ogni riga aspetta che la precedente finisca console.log('1'); console.log('2'); console.log('3'); // → stampa sempre 1, 2, 3 in ordine, senza sorprese // Codice ASINCRONO: alcune operazioni "aspettano" senza bloccare il resto console.log('1'); setTimeout(() => console.log('2'), 1000); // eseguito dopo 1 secondo console.log('3'); // → stampa 1, 3, e SOLO DOPO (1 secondo dopo) stampa 2!
⚠️ Questo è il concetto più importante e sorprendente per chi inizia: il codice asincrono non blocca l'esecuzione delle righe successive — "3" viene stampato prima di "2", anche se "2" è scritto prima nel codice.
🎁 Promise — una "scatola" che conterrà un valore futuro
Una Promise rappresenta il risultato (futuro) di un'operazione asincrona. Può trovarsi in 3 stati: pending (in attesa), fulfilled (risolta con successo) o rejected (fallita con un errore).
const promessaSemplice = new Promise((resolve, reject) => { setTimeout(() => { const successo = true; if (successo) { resolve('Dati ricevuti!'); // la promise si RISOLVE con questo valore } else { reject('Errore di rete'); // la promise viene RIFIUTATA } }, 1000); }); promessaSemplice .then(risultato => console.log(risultato)) // eseguito se resolve() .catch(errore => console.log('Errore:', errore)); // eseguito se reject()
💡 then/catch sono il modo "classico" di gestire una Promise: .then() riceve il valore quando tutto va bene, .catch() intercetta eventuali errori — molto simile concettualmente a un try/catch.
✨ async/await — la sintassi moderna che sembra sincrona
async/await (ES2017) è "zucchero sintattico" sopra le Promise: permette di scrivere codice asincrono che si legge come se fosse sincrono, riga dopo riga, senza le catene di .then() annidate.
// Una funzione deve essere dichiarata "async" per poter usare "await" al suo interno: async function caricaDati() { console.log('Inizio caricamento...'); const risultato = await promessaSemplice; // "aspetta" che la Promise si risolva console.log(risultato); console.log('Fine!'); } caricaDati(); // → Inizio caricamento..., poi (dopo l'attesa) Dati ricevuti!, poi Fine!
⚠️ await funziona SOLO dentro una funzione dichiarata async — non puoi usarlo in una funzione normale, né direttamente nello script principale (in molti contesti, senza wrapping speciale).
🔄 Confronto diretto: .then() vs async/await
// Stile .then() — annidamento che cresce con più passaggi: caricaUtente() .then(utente => caricaOrdini(utente.id)) .then(ordini => console.log(ordini)) .catch(errore => console.log(errore)); // Stile async/await — stesso risultato, più leggibile: async function mostraOrdini() { try { const utente = await caricaUtente(); const ordini = await caricaOrdini(utente.id); console.log(ordini); } catch (errore) { console.log(errore); } }
✅ Con più passaggi asincroni concatenati, async/await resta molto più leggibile del corrispondente stile .then() — per questo è diventato lo standard preferito nel codice JavaScript moderno.
🌐 Fetch API — richiedere dati da un server
fetch() è la funzione integrata del browser per fare richieste HTTP (chiamare API esterne, caricare dati da un server) — restituisce sempre una Promise.
async function caricaPost() { const risposta = await fetch('https://api.esempio.it/posts/1'); const dati = await risposta.json(); // converte la risposta in oggetto JS (anche questo è async!) console.log(dati); } caricaPost();
⚠️ Doppio await necessario: serve await sia su fetch() stesso (per ottenere la risposta) sia su .json() (perché anche estrarre e "parsare" il corpo della risposta è un'operazione asincrona) — dimenticare uno dei due è un errore molto comune.
📤 Fetch con parametri — invio dati con POST
async function creaOrdine(datiOrdine) { const risposta = await fetch('https://api.esempio.it/ordini', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(datiOrdine) // ricordi JSON.stringify dalla guida su Oggetti? }); const risultato = await risposta.json(); return risultato; }
💡 Fetch collega insieme concetti già visti: async/await per la gestione asincrona, JSON.stringify/parse per il formato dei dati — è il punto in cui tutta la parte "moderna" di JavaScript converge in un caso d'uso reale.
⚠️ Gestire gli errori con try/catch
Con async/await, gli errori (incluse le Promise rifiutate) si gestiscono con try/catch, lo stesso costrutto usato per il codice sincrono.
async function caricaDatiSicuro() { try { const risposta = await fetch('https://api.esempio.it/dati'); if (!risposta.ok) { throw new Error(`Errore HTTP: ${risposta.status}`); } const dati = await risposta.json(); console.log(dati); } catch (errore) { console.log('Qualcosa è andato storto:', errore.message); } }
⚠️ Attenzione: fetch() non lancia un errore per risposte HTTP di errore (404, 500)! Considera "fallita" una richiesta solo per problemi di rete reali (server irraggiungibile). Per errori HTTP, va controllato manualmente risposta.ok come sopra.
🧪 Playground — prova il codice asincrono dal vivo
Il playground supporta funzioni async — prova questo esempio simulato (senza rete reale, con Promise e setTimeout).
Editor JS
// il risultato apparirà qui (potrebbe richiedere un istante per l'output asincrono)