惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

G
Google Developers Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
V
Visual Studio Blog
雷峰网
雷峰网
博客园_首页
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
爱范儿
爱范儿
小众软件
小众软件
D
Docker
P
Proofpoint News Feed
B
Blog
Vercel News
Vercel News
B
Blog RSS Feed
U
Unit 42
月光博客
月光博客
The GitHub Blog
The GitHub Blog
Apple Machine Learning Research
Apple Machine Learning Research
Y
Y Combinator Blog
I
InfoQ
Recent Announcements
Recent Announcements

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Event Loop - Entendendo uma das bases do Node
João Victor · 2026-06-18 · via DEV Community

João Victor

O Event Loop é o mecanismo responsável por decidir quando callbacks e continuidades de operações assíncronas devem ser executados. Ele não executa operações de I/O diretamente, mas organiza a ordem em que elas retornam para o JavaScript. Essa arquitetura permite que o Node.js mantenha uma única thread de execução para JavaScript, enquanto delega operações de rede, disco e sistema operacional para componentes especializados do runtime e do próprio sistema operacional.

Início

Quando iniciamos um processo Node.js, o runtime carrega o arquivo de entrada da aplicação e executa todo o código síncrono disponível na Call Stack. Somente após essa etapa o Event Loop passa a assumir o controle do fluxo da aplicação, verificando continuamente quais callbacks estão prontos para execução.

   │           timers          │
   └─────────────┬─────────────┘
                 │
                 v
   ┌───────────────────────────┐
┌─>│     pending callbacks     │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │       idle, prepare       │
│  └─────────────┬─────────────┘      ┌───────────────┐
│  ┌─────────────┴─────────────┐      │   incoming:   │
│  │           poll            │<─────┤  connections, │
│  └─────────────┬─────────────┘      │   data, etc.  │
│  ┌─────────────┴─────────────┐      └───────────────┘
│  │           check           │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
│  │      close callbacks      │
│  └─────────────┬─────────────┘
│  ┌─────────────┴─────────────┐
└──┤           timers          │
   └───────────────────────────┘

Trecho retirado da documentação principal.

Sobre o Event Loop

Durante muito tempo tratei o Event Loop como um dos conceitos mais complexos do Node.js. Depois de estudar a documentação oficial com mais calma, percebi que a dificuldade não está no Event Loop em si, mas na quantidade de conceitos diferentes que normalmente são apresentados ao mesmo tempo: libuv, Call Stack, Promises, Microtasks, Sistema Operacional e I/O.
Quando isolamos o papel do Event Loop, ele se torna surpreendentemente simples.

Definindo os passos e apresentando o iceberg 🧊

O Event Loop não executa trabalho. Ele agenda trabalho.

Acredito que o principal problema para entender o Event Loop esteja na confusão entre os contextos. Em um primeiro momento, imaginamos que o Event Loop é o "MacGyver" do runtime ou algo extremamente complexo. Porém, não é.

O interessante na arquitetura do runtime é como cada parte é extremamente especializada. Quando falamos de Event Loop, estamos falando única e simplesmente sobre quando executar um callback.

Pense no seguinte: a execução do JavaScript ocorre em uma única thread. Isso significa que os comandos vão rodar de forma linear, um após o outro, obrigatoriamente. Portanto, precisamos de algum mecanismo de coordenação para que o runtime seja minimamente confiável e siga um fluxo previsível.

Outro ponto extremamente importante: quando ouvimos falar em Call Stack, Microtasks e Event Loop, devemos entender que o Event Loop não possui uma Call Stack própria. Além disso, uma microtask tem muito mais relação com a Call Stack do que com o próprio Event Loop.

Se o assunto é Event Loop, podemos defini-lo como uma lista de prioridades para callbacks de naturezas diferentes. Isso explica o que ele faz, mas não explica como.

O Event Loop é um consumidor

Imagine o seguinte: o Event Loop tem como função depositar na Call Stack todos os callbacks que estão na fila da fase atual. Pense em cada fase como uma fila e no Event Loop como um consumidor.
Ele percorre obrigatoriamente as seguintes fases:

  • Timers
  • Pending Callbacks
  • Idle
  • Prepare
  • Poll
  • Check
  • Close Callbacks

Assim que você executa um código com Node.js, o fluxo ocorre da seguinte forma:

  • O Event Loop seleciona callbacks da fase atual e os coloca na Call Stack para execução.
  • A Call Stack executa um callback e, ao final da execução, drena a fila de microtasks. É aqui que entram as Promises resolvidas e as continuações geradas por async/await.
  • Após limpar a fila de microtasks, o runtime avança para a próxima fase do Event Loop.
  • O processo se repete até o encerramento da aplicação. Note que uma fase não possui necessariamente uma Call Stack própria. O runtime possui apenas uma Call Stack e uma fila de microtasks. As fases do Event Loop existem para determinar quais callbacks podem ser executados em cada momento.

Nem todas as fases são para você

Apesar de o diagrama do Event Loop apresentar sete fases, nem todas existem para que desenvolvedores JavaScript agendem callbacks diretamente.
Algumas fases são utilizadas internamente pela libuv para preparação e coordenação do runtime. Na prática, como desenvolvedor Node.js, você interage principalmente com Timers, Pending Callbacks, Poll, Check e Close Callbacks.

As fases Idle e Prepare, por exemplo, existem para permitir que a libuv realize atividades internas antes de entrar na fase de processamento de eventos. Embora façam parte do ciclo do Event Loop, dificilmente você terá contato direto com elas durante o desenvolvimento de aplicações.

Timers

Responsável por executar callbacks agendados por temporizadores.
Exemplos:

setTimeout(() => {
  console.log('Executado após 1 segundo');
}, 1000);
setInterval(() => {
  console.log('Executado periodicamente');
}, 5000);

Importante: o tempo informado representa o tempo mínimo de espera. Não existe garantia de execução exata naquele instante.

Pending Callbacks

Executa callbacks de determinadas operações que foram adiadas para a próxima iteração do Event Loop.
Essa fase é pouco utilizada diretamente por desenvolvedores, mas é frequentemente utilizada internamente pelo Node.js para reportar erros ou resultados de operações assíncronas.
Exemplo conceitual:

socket.on('error', (err) => {
  console.log(err);
});

Alguns callbacks relacionados a erros de rede e TCP podem passar por essa fase antes de serem executados.

Idle e Prepare

As fases Idle e Prepare são utilizadas internamente pela libuv para coordenar o funcionamento do runtime antes da entrada na fase Poll.
Durante essas etapas, a libuv realiza verificações, preparações e atividades de manutenção necessárias para o funcionamento correto do Event Loop. Apesar de fazerem parte oficialmente do ciclo, elas não possuem APIs públicas para que desenvolvedores registrem callbacks diretamente.
Exemplos
Não existem APIs JavaScript que permitam agendar callbacks para essas fases.

// Não existe algo equivalente a isso

idle(() => {});
prepare(() => {});

Quando utilizar
Nunca diretamente.
Como desenvolvedor Node.js, você normalmente interage apenas com as fases:

  • Timers
  • Pending Callbacks
  • Poll
  • Check
  • Close Callbacks #### Poll É a fase mais importante do Event Loop. Aqui a libuv verifica se existem operações de I/O concluídas e callbacks aguardando execução. Exemplos:
fs.readFile('arquivo.txt', (err, data) => {
  console.log(data.toString());
});
http.createServer((req, res) => {
  res.end('Olá');
});
database.query('SELECT * FROM users', callback);

Leitura de arquivos, conexões de rede, requisições HTTP e diversas operações assíncronas costumam retornar seus callbacks para esta fase.

Check

Executada logo após a fase Poll.
É a fase utilizada pelo setImmediate().
Exemplo:

setImmediate(() => {
  console.log('Executado na fase Check');
});

Uma forma simples de pensar é:

  • setTimeout(..., 0) → Timers
  • setImmediate(...) → Check

Close Callbacks

Executa callbacks relacionados ao encerramento de recursos.
Exemplo:

socket.on('close', () => {
  console.log('Conexão encerrada');
});
stream.on('close', () => {
  console.log('Stream finalizada');
});

Essa fase permite que recursos sejam liberados corretamente antes do término definitivo da operação.

Conclusão

O assustador Event Loop é, na prática, apenas um coordenador das nossas invocações. Toda a parte pesada acontece entre o kernel do sistema operacional e a libuv.