13 de Janeiro de 2025
Event Loop de Verdade no Browser
Como entender a ordem real entre código síncrono, microtasks, timers, eventos e renderização sem misturar tudo numa fila imaginaria só.
Andrews Ribeiro
Founder & Engineer
4 min Intermediario Frontend
O problema
Muita explicação sobre event loop para cedo demais na história.
Ela mostra:
- call stack
- microtask queue
- macrotask queue
E pronto.
Só que no browser o problema real quase nunca e só prever a ordem entre dois console.log.
O problema real e este:
- por que o clique demorou a responder?
- por que o
setTimeoutatrasou? - por que eu mudei o DOM e a tela ainda não pintou?
Modelo mental
No browser, o event loop coordena a thread principal entre quatro tipos de pressao:
- código síncrono rodando agora
- microtasks pendentes
- tasks como timer e eventos
- oportunidade de renderização
Se quiser uma frase simples:
enquanto a thread principal esta ocupada demais, o browser não consegue te obedecer direito.
Isso vale para:
- executar JS
- responder input
- processar timer
- atualizar a tela
Quebrando o problema
Código síncrono segura tudo
Enquanto um bloco síncrono esta rodando, nada entra no meio.
Se você faz trabalho pesado ali:
- clique espera
- timer espera
- renderização espera
O browser não esta ignorando você.
Ele esta ocupado.
Microtasks vem antes da proxima task
Depois que o código atual termina, o ambiente esvazia microtasks pendentes.
Aqui entram coisas como:
Promise.thencatchfinally- continuacao de
await
Por isso Promise.then costuma aparecer antes de setTimeout(..., 0).
Não e porque promise e “mais rápida”.
E porque a prioridade da fila e diferente.
Timers e eventos esperam a vez deles
setTimeout(..., 0) não significa “agora”.
Significa só que aquela task ficou elegivel cedo.
Ela ainda precisa esperar:
- o código síncrono atual acabar
- as microtasks pendentes esvaziarem
O mesmo vale para muita coisa ligada a evento e callbacks do ambiente.
Renderização também precisa de janela
Esse ponto costuma limpar bastante a confusao de frontend.
Você pode mudar o DOM agora, mas a pintura na tela depende de o browser conseguir chegar na etapa de renderização.
Se você faz isto:
- muda o estado
- muda o DOM
- roda um bloco pesado logo em seguida
a tela pode parecer “atrasada” porque a thread principal não liberou espaco para o browser pintar.
Exemplo simples
Olhe este fluxo:
button.addEventListener('click', async () => {
box.textContent = 'Carregando...'
await Promise.resolve()
console.log('microtask')
const start = Date.now()
while (Date.now() - start < 200) {}
setTimeout(() => {
console.log('timeout')
}, 0)
})
O que costuma acontecer:
- o click agenda o handler
- o texto muda no DOM
- a continuacao do
awaitentra como microtask - o bloco pesado prende a thread
- o timer fica esperando
- a pintura também pode ficar esperando
Ou seja:
você mudou o DOM cedo, mas ainda assim a interface pode não parecer responsiva imediatamente.
Isso confunde porque muita gente pensa que “mexer no DOM” e igual a “ver na tela”.
Não e.
Erros comuns
- Achar que
setTimeout(..., 0)significa execução imediata. - Dizer que promise e mais rápida em vez de explicar prioridade.
- Esquecer que microtasks demais também atrasam a vida do browser.
- Tratar renderização como se acontecesse automaticamente no mesmo instante da mudança.
- Ignorar que thread principal compartilha JS, input e pintura.
Como um senior pensa
Quem tem mais experiência costuma olhar para UI travando e pensar:
“O que esta monopolizando a thread principal? Trabalho síncrono? Microtasks demais? Renderização sem janela?”
Essa pergunta e muito mais útil do que ficar repetindo nomes de fila.
Porque leva para ação real:
- quebrar trabalho pesado
- adiar parte do processamento
- mover trabalho para outro lugar
- reduzir bloqueio antes da pintura
O que o entrevistador quer ver
Em entrevista, event loop no browser costuma separar bem quem decorou termo de quem consegue depurar interface de verdade.
O avaliador quer ver se você:
- explica a ordem de execução com clareza
- conecta microtask e timer sem supersticao
- menciona thread principal e renderização
- relaciona isso a input lag e jank
Uma resposta forte costuma soar assim:
“No browser, o event loop não decide só a ordem do JavaScript. Ele também afeta quando eventos entram e quando a tela consegue pintar. Se eu prendo a thread principal, atraso timer, input e renderização ao mesmo tempo.”
Event loop entendido pela metade explica
console.log. Entendido direito explica interface travando.
Resumo rápido
O que vale manter na cabeça
- No browser, event loop coordena script, microtasks, eventos e oportunidades de renderização.
- `Promise.then` e continuacao de `await` costumam rodar antes de timers elegiveis porque entram como microtasks.
- Trabalho síncrono pesado pode atrasar clique, timer e pintura ao mesmo tempo porque tudo divide a thread principal.
- Entender o event loop no browser ajuda mais no debug de UI travando do que decorar nome de fila.
Checklist de pratica
Use isto ao responder
- Consigo explicar a ordem entre código síncrono, microtasks e `setTimeout`?
- Sei dizer por que a tela pode não atualizar mesmo depois de eu mudar o DOM?
- Consigo relacionar event loop com jank e bloqueio da thread principal?
- Sei responder diferencas praticas entre o raciocínio do browser e o do Node?
Você concluiu este artigo
Próximo passo
Como o event loop funciona Próximo passo →Compartilhar esta página
Copie o link manualmente no campo abaixo.