Menu

Sleep em TypeScript: como esperar ou dar um delay

O TypeScript não tem um sleep embutido, mas uma linha resolve: uma função que retorna uma Promise<void> resolvida por setTimeout. Veja como usá-la com await, pausar dentro de loops, tentar de novo com um intervalo, cancelar um sleep e por que não existe sleep bloqueante em JavaScript.

Esta página tem editores executáveis - edite, execute e veja a saída na hora.

O TypeScript não tem um sleep embutido. Escreva uma função que retorna uma Promise<void> que o setTimeout resolve depois do intervalo, e use await nela dentro de uma função async:

await sleep(300) pausa só a main. O programa não fica congelado: timers, outras funções async e I/O continuam rodando enquanto ela espera.

Como a função sleep funciona

setTimeout(resolve, ms) agenda resolve para ser chamado depois de ms milissegundos, e chamar resolve resolve a promise. O await nessa promise suspende a função async até lá.

O argumento de tipo <void> importa. Um new Promise(...) isolado não infere o seu tipo a partir das chamadas de resolve, então sem ele sleep retornaria Promise<unknown>. E é o void que permite chamar resolve sem valor: em uma Promise<number>, resolve() sem argumento é erro de compilação. Quando a função tem um tipo de retorno declarado, o argumento de tipo pode ir ali:

setTimeout garante um mínimo, não um tempo exato: o callback roda quando o intervalo já passou e o event loop está livre. Conte com alguns milissegundos de folga.

Sleep dentro de um loop

await sleep() dentro de um loop for ou for...of faz uma pausa entre as iterações, e é assim que você controla o ritmo do trabalho (limites de taxa, polling, animações no terminal):

Isso não funciona dentro de forEach: ele ignora a promise que cada callback async retorna, então todas as iterações começam ao mesmo tempo e nada espera. Use um loop for ou for...of, como explicado na página de async/await.

Retry com delay

Um uso real comum: tentar uma operação e, se ela falhar, esperar e tentar de novo, dobrando a espera a cada vez (exponential backoff).

O return await fn() dentro do try importa: sem await, uma promise rejeitada seria retornada antes que o catch pudesse vê-la.

Um sleep cancelável

Um sleep simples não pode ser interrompido. Para parar de esperar antes (o usuário clicou em Cancelar, um desligamento começou), passe um AbortSignal e limpe o timer quando ele disparar:

O programa termina logo depois do abort porque o timer longo foi limpo. Sem clearTimeout, o Node continuaria rodando até os 5 segundos passarem.

Os timers com promise embutidos no Node

O Node traz uma versão com promise de setTimeout no módulo node:timers/promises, então em código Node você pode importá-la em vez de escrever o helper. Ela também aceita um valor para resolver e um 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
}

Os tipos vêm de @types/node (npm i -D @types/node). Esse módulo não existe nos navegadores, onde o helper de uma linha é a escolha portável.

Não existe sleep bloqueante

Linguagens com threads têm um sleep que bloqueia a thread atual. O JavaScript roda o seu código em uma única thread com um event loop, então um sleep bloqueante congelaria todo o resto: nenhum timer dispara, nenhuma resposta de rede é tratada e, no navegador, a página para de responder. Um loop ocupado que gira até o relógio passar de um certo horário faz exatamente isso, e nunca é a ferramenta certa.

O sleep assíncrono é o jeito como a espera funciona em JavaScript e TypeScript: a função é suspensa, a thread fica livre e a função retoma quando o timer dispara. Atomics.wait pode bloquear de verdade, mas só em um SharedArrayBuffer, e os navegadores o proíbem na thread principal; ele existe para coordenar worker threads, não para delays.

Perguntas frequentes

Como fazer um sleep no TypeScript?

Defina const sleep = (ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)); e chame await sleep(1000) dentro de uma função async. Isso pausa essa função por cerca de um segundo sem bloquear o resto do programa.

Existe uma função sleep embutida no TypeScript?

Não. O TypeScript adiciona tipos ao JavaScript e não tem uma biblioteca de tempo de execução própria, e o JavaScript não tem sleep. No Node você pode importar uma: import { setTimeout as sleep } from "node:timers/promises". No navegador, escreva o helper de uma linha.

Por que o sleep precisa de await?

sleep(1000) retorna uma promise na hora; só o await pausa a função async em volta até ela resolver. Sem await, a próxima linha roda imediatamente. await só funciona em uma função async (ou no nível superior de um módulo ES).

Posso bloquear a thread com um sleep síncrono no TypeScript?

Não em código normal. O JavaScript roda em uma thread só com um event loop, e um loop de espera ativa congela tudo: timers, callbacks de rede, a página inteira. Use o sleep assíncrono. Atomics.wait pode bloquear uma thread no Node ou em um worker, mas isso serve para coordenação de workers em baixo nível, não para delays.

Coddy programming languages illustration

Aprenda a programar com o Coddy

COMEÇAR