TypeScript hat kein eingebautes sleep. Schreibe eine Funktion, die ein Promise<void> zurückgibt, das setTimeout nach der Verzögerung auflöst, und warte dann in einer async-Funktion mit await darauf:
await sleep(300) pausiert nur main. Das Programm ist nicht eingefroren: Timer, andere async-Funktionen und I/O laufen weiter, während es wartet.
Wie die sleep-Funktion funktioniert
setTimeout(resolve, ms) plant, dass resolve nach ms Millisekunden aufgerufen wird, und der Aufruf von resolve schließt das Promise ab. await auf dieses Promise hält die async-Funktion bis dahin an.
Das Typargument <void> ist wichtig. Ein alleinstehendes new Promise(...) leitet seinen Typ nicht aus den Aufrufen von resolve ab, ohne es würde sleep also Promise<unknown> zurückgeben. Und void erlaubt, resolve ohne Wert aufzurufen: In einem Promise<number> ist resolve() ohne Argument ein Compilerfehler. Hat die Funktion einen deklarierten Rückgabetyp, kann das Typargument stattdessen dort stehen:
setTimeout garantiert eine Mindestzeit, keine genaue: Der Callback läuft, wenn die Verzögerung vorbei und die Event Loop frei ist. Rechne mit ein paar Millisekunden Spielraum.
sleep in einer Schleife
await sleep() in einer Schleife mit for oder for...of pausiert zwischen den Durchläufen, und so taktest du Arbeit (Rate Limits, Polling, Animationen im Terminal):
In forEach funktioniert das nicht: Es ignoriert das Promise, das jeder async-Callback zurückgibt, also starten alle Durchläufe auf einmal, und nichts wartet. Nimm eine Schleife mit for oder for...of, wie auf der Seite zu async/await erklärt.
Retry mit Verzögerung
Ein häufiger echter Einsatz: Probiere eine Operation, und wenn sie scheitert, warte und versuche es erneut, wobei sich die Wartezeit jedes Mal verdoppelt (Exponential Backoff).
Das return await fn() im try ist wichtig: Ohne await würde ein abgelehntes Promise zurückgegeben, bevor der catch es sehen könnte.
Ein abbrechbares sleep
Ein einfaches sleep lässt sich nicht unterbrechen. Um früher mit dem Warten aufzuhören (jemand hat auf Abbrechen gedrückt, ein Shutdown hat begonnen), übergib ein AbortSignal und lösche den Timer, wenn es auslöst:
Das Programm endet direkt nach dem Abbruch, weil der lange Timer gelöscht wurde. Ohne clearTimeout würde Node weiterlaufen, bis die 5 Sekunden um sind.
Die eingebauten Promise-Timer von Node
Node liefert im Modul node:timers/promises eine Promise-Version von setTimeout mit, in Node-Code kannst du sie also importieren, statt die Hilfsfunktion zu schreiben. Sie akzeptiert auch einen Wert, mit dem aufgelöst wird, und ein 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
}
Die Typen kommen aus @types/node (npm i -D @types/node). Dieses Modul gibt es in Browsern nicht, dort ist die einzeilige Hilfsfunktion die portable Wahl.
Es gibt kein blockierendes sleep
Sprachen mit Threads haben ein sleep, das den aktuellen Thread blockiert. JavaScript führt deinen Code auf einem einzigen Thread mit einer Event Loop aus, ein blockierendes sleep würde also alles andere einfrieren: Keine Timer lösen aus, keine Netzwerkantworten werden verarbeitet, und im Browser reagiert die Seite nicht mehr. Eine Busy-Schleife, die dreht, bis die Uhr einen Zeitpunkt überschreitet, tut genau das und ist nie das richtige Werkzeug.
Das asynchrone sleep ist die Art, wie Warten in JavaScript und TypeScript funktioniert: Die Funktion wird angehalten, der Thread ist frei, und die Funktion läuft weiter, wenn der Timer auslöst. Atomics.wait kann wirklich blockieren, aber nur auf einem SharedArrayBuffer, und Browser verbieten es im Hauptthread; es dient der Koordination von Worker-Threads, nicht für Verzögerungen.
Häufig gestellte Fragen
Wie mache ich ein sleep in TypeScript?
Definiere const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)); und rufe await sleep(1000) in einer async-Funktion auf. Das pausiert diese Funktion für etwa eine Sekunde, ohne den Rest des Programms zu blockieren.
Gibt es in TypeScript eine eingebaute sleep-Funktion?
Nein. TypeScript fügt JavaScript Typen hinzu und hat keine eigene Laufzeitbibliothek, und JavaScript hat kein sleep. In Node kannst du eines importieren: import { setTimeout as sleep } from "node:timers/promises". Im Browser schreibst du die einzeilige Hilfsfunktion.
Warum braucht sleep ein await?
sleep(1000) gibt sofort ein Promise zurück; erst await pausiert die umgebende async-Funktion, bis es aufgelöst ist. Ohne await läuft die nächste Zeile sofort. await funktioniert nur in einer async-Funktion (oder auf oberster Ebene eines ES-Moduls).
Kann ich in TypeScript den Thread mit einem synchronen sleep blockieren?
In normalem Code nicht. JavaScript läuft auf einem Thread mit einer Event Loop, und eine Busy-Wait-Schleife friert alles ein: Timer, Netzwerk-Callbacks, die ganze Seite. Nimm stattdessen das asynchrone sleep. Atomics.wait kann in Node oder in einem Worker einen Thread blockieren, aber das dient der Koordination von Workern auf niedriger Ebene, nicht für Verzögerungen.