TypeScript non ha uno sleep integrato. Scrivi una funzione che restituisce una Promise<void> che setTimeout risolve dopo il ritardo, poi fanne l'await dentro una funzione async:
await sleep(300) mette in pausa solo main. Il programma non si blocca: i timer, le altre funzioni async e l'I/O continuano a girare mentre aspetta.
Come funziona la funzione sleep
setTimeout(resolve, ms) programma la chiamata a resolve dopo ms millisecondi, e chiamare resolve conclude la promise. Un await su quella promise sospende la funzione async fino a quel momento.
L'argomento di tipo <void> è importante. Un new Promise(...) da solo non inferisce il suo tipo dalle chiamate a resolve, quindi senza di esso sleep restituirebbe Promise<unknown>. Ed è void che permette di chiamare resolve senza valore: in una Promise<number>, resolve() senza argomenti è un errore di compilazione. Quando la funzione ha un tipo di ritorno dichiarato, l'argomento di tipo può andare lì:
setTimeout garantisce un tempo minimo, non esatto: la callback viene eseguita quando il ritardo è trascorso e l'event loop è libero. Mettiti in conto qualche millisecondo di margine.
Sleep dentro un ciclo
await sleep() dentro un ciclo for o for...of fa una pausa tra un'iterazione e l'altra, ed è così che dosi il lavoro (limiti di frequenza, polling, animazioni nel terminale):
Non funziona dentro forEach: ignora la promise restituita da ogni callback async, quindi tutte le iterazioni partono insieme e nulla aspetta. Usa un ciclo for o for...of, come spiegato nella pagina su async/await.
Riprovare con un ritardo
Un uso reale comune: prova un'operazione e, se fallisce, aspetta e riprova, raddoppiando l'attesa ogni volta (exponential backoff).
Il return await fn() dentro il try è importante: senza await, una promise rifiutata verrebbe restituita prima che il catch possa vederla.
Uno sleep annullabile
Uno sleep semplice non si può interrompere. Per smettere di aspettare prima (l'utente ha premuto Annulla, è iniziato uno spegnimento), passa un AbortSignal e cancella il timer quando scatta:
Il programma termina subito dopo l'annullamento perché il timer lungo è stato cancellato. Senza clearTimeout, Node continuerebbe a girare finché non fossero trascorsi i 5 secondi.
I timer con promise integrati in Node
Node include una versione con promise di setTimeout nel modulo node:timers/promises, quindi nel codice Node puoi importarla invece di scrivere l'helper. Accetta anche un valore con cui risolversi e un AbortSignal:
import { setTimeout as sleep } from "node:timers/promises";
async function main() {
await sleep(1000); // wait one second
const result = await sleep(500, "done"); // resolves with "done"
const ac = new AbortController();
await sleep(10_000, undefined, { signal: ac.signal }); // cancellable
}
I tipi arrivano da @types/node (npm i -D @types/node). Questo modulo non esiste nei browser, dove l'helper di una riga è la scelta portabile.
Non esiste uno sleep bloccante
I linguaggi con i thread hanno uno sleep che blocca il thread corrente. JavaScript esegue il tuo codice su un solo thread con un event loop, quindi uno sleep bloccante congelerebbe tutto il resto: nessun timer scatta, nessuna risposta di rete viene gestita, e in un browser la pagina smette di rispondere. Un ciclo attivo che gira finché l'orologio non supera un certo istante fa esattamente questo, e non è mai lo strumento giusto.
Lo sleep asincrono è il modo in cui si aspetta in JavaScript e TypeScript: la funzione viene sospesa, il thread è libero, e la funzione riprende quando scatta il timer. Atomics.wait può bloccare davvero, ma solo su uno SharedArrayBuffer, e i browser lo vietano sul thread principale; esiste per coordinare i worker thread, non per creare ritardi.
Domande frequenti
Come faccio uno sleep in TypeScript?
Definisci const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)); e chiama await sleep(1000) dentro una funzione async. Mette in pausa quella funzione per circa un secondo senza bloccare il resto del programma.
Esiste una funzione sleep integrata in TypeScript?
No. TypeScript aggiunge i tipi a JavaScript e non ha una propria libreria di runtime, e JavaScript non ha sleep. In Node puoi importarne una: import { setTimeout as sleep } from "node:timers/promises". Nel browser, scrivi la funzione helper di una riga.
Perché sleep ha bisogno di await?
sleep(1000) restituisce subito una promise; solo await mette in pausa la funzione async che la contiene finché non si risolve. Senza await, la riga successiva viene eseguita immediatamente. await funziona solo in una funzione async (o al livello più alto di un ES module).
Posso bloccare il thread con uno sleep sincrono in TypeScript?
Non nel codice normale. JavaScript gira su un solo thread con un event loop, e un ciclo di attesa attiva blocca tutto: i timer, le callback di rete, l'intera pagina. Usa invece lo sleep asincrono. Atomics.wait può bloccare un thread in Node o in un worker, ma serve a coordinare i worker a basso livello, non a creare ritardi.