⏱️ 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.