<h2>O que é Event Loop e sua Estrutura Fundamental</h2>
<p>O Event Loop é o mecanismo central que permite ao JavaScript executar código assíncrono em uma linguagem single-threaded. Compreender sua estrutura é essencial para escrever código performático e previsível. O Event Loop não é parte da especificação do JavaScript em si, mas sim da implementação das engines (como V8 do Chrome), trabalhando em conjunto com as APIs fornecidas pelo ambiente (browser ou Node.js).</p>
<p>A execução segue um ciclo: o Event Loop verifica a Call Stack, executa o código síncrono, depois processa as filas de microtasks e macrotasks. Esse processo se repete continuamente. A ordem de execução é: <strong>Call Stack → Microtasks → Rendering → Macrotasks → (volta ao início)</strong>. Compreender essa sequência é crucial para prever quando seu código será executado.</p>
<h2>Microtasks vs Macrotasks: A Hierarquia de Prioridades</h2>
<h3>O que são Microtasks?</h3>
<p>Microtasks têm prioridade máxima e são executadas após cada macrotask. Elas incluem: <code>Promise.then()</code>, <code>Promise.catch()</code>, <code>Promise.finally()</code>, <code>MutationObserver</code> e <code>queueMicrotask()</code>. A característica distintiva é que <strong>todas as microtasks na fila são processadas antes de qualquer macrotask</strong>.</p>
<pre><code class="language-javascript">console.log('1. Sincronizado');
setTimeout(() => {
console.log('2. Macrotask (setTimeout)');
}, 0);
Promise.resolve()
.then(() => {
console.log('3. Microtask (Promise)');
})
.then(() => {
console.log('4. Microtask (Promise 2)');
});
console.log('5. Sincronizado 2');
// Saída:
// 1. Sincronizado
// 5. Sincronizado 2
// 3. Microtask (Promise)
// 4. Microtask (Promise 2)
// 2. Macrotask (setTimeout)</code></pre>
<h3>O que são Macrotasks?</h3>
<p>Macrotasks incluem: <code>setTimeout()</code>, <code>setInterval()</code>, <code>setImmediate()</code> (Node.js), eventos DOM (<code>click</code>, <code>load</code>), e requisições HTTP. <strong>Apenas uma macrotask é executada por ciclo do Event Loop</strong>. Após cada macrotask, todas as microtasks pendentes são processadas antes de qualquer macrotask subsequente.</p>
<pre><code class="language-javascript">setTimeout(() => {
console.log('Macrotask 1');
Promise.resolve().then(() => console.log('Microtask após Macrotask 1'));
}, 0);
setTimeout(() => {
console.log('Macrotask 2');
}, 0);
// Saída:
// Macrotask 1
// Microtask após Macrotask 1
// Macrotask 2</code></pre>
<p>Essa hierarquia existe porque Promises são fundamentais para o modelo assíncrono moderno, enquanto macrotasks são operações mais pesadas que exigem controle de quando são executadas.</p>
<h2>requestAnimationFrame: O Timing Perfeito para Animações</h2>
<h3>Onde se Encaixa no Event Loop?</h3>
<p><code>requestAnimationFrame()</code> (rAF) não é exatamente um microtask nem um macrotask. É executado <strong>entre as microtasks e a renderização</strong>, garantindo que seu código rode sincronizado com a taxa de refresh da tela (60fps ou 120fps). Isso o torna ideal para animações e manipulação do DOM.</p>
<pre><code class="language-javascript">console.log('1. Início');
setTimeout(() => {
console.log('2. setTimeout');
}, 0);
requestAnimationFrame(() => {
console.log('3. requestAnimationFrame');
});
Promise.resolve().then(() => {
console.log('4. Promise');
});
console.log('5. Fim síncrono');
// Saída:
// 1. Início
// 5. Fim síncrono
// 4. Promise
// 3. requestAnimationFrame (antes da renderização)
// 2. setTimeout</code></pre>
<h3>Exemplo Prático: Animação Eficiente</h3>
<pre><code class="language-javascript">let position = 0;
function animate() {
position += 5;
const element = document.getElementById('box');
element.style.left = position + 'px';
if (position < 300) {
requestAnimationFrame(animate);
}
}
// Usar rAF é mais eficiente que setInterval
// porque sincroniza com a renderização do navegador
requestAnimationFrame(animate);
// Evite isto:
// setInterval(() => {
// position += 5;
// element.style.left = position + 'px';
// }, 16); // Pode desincronizar do refresh</code></pre>
<h2>Casos Práticos: Integrando Tudo Junto</h2>
<h3>Caso 1: Carregamento de Dados com Animação</h3>
<pre><code class="language-javascript">async function fetchAndAnimate() {
console.log('1. Iniciando fetch');
// Macrotask: requisição HTTP
const response = await fetch('/api/data');
// Microtask: processamento do Promise
const data = await response.json();
console.log('2. Dados recebidos');
// rAF: renderização suave
requestAnimationFrame(() => {
document.getElementById('content').innerHTML = data.message;
console.log('3. DOM atualizado');
});
}
// setTimeout garante execução assíncrona
setTimeout(() => {
fetchAndAnimate();
}, 0);</code></pre>
<h3>Caso 2: Batching de Atualizações</h3>
<pre><code class="language-javascript">const updates = [];
function scheduleUpdate(callback) {
updates.push(callback);
// Microtask: agrupa múltiplas atualizações
Promise.resolve().then(() => {
console.log(Processando ${updates.length} atualizações);
updates.forEach(cb => cb());
updates.length = 0;
});
}
// Chamadas síncronas
scheduleUpdate(() => console.log('Update 1'));
scheduleUpdate(() => console.log('Update 2'));
scheduleUpdate(() => console.log('Update 3'));
// Saída:
// Processando 3 atualizações
// Update 1
// Update 2
// Update 3</code></pre>
<p>Esse padrão é usado internamente por frameworks como React para otimizar renderizações.</p>
<h2>Conclusão</h2>
<p>Os três conceitos principais que você deve dominar são: <strong>(1) Microtasks sempre executam antes de macrotasks</strong>, garantindo que Promises sejam processadas com alta prioridade; <strong>(2) requestAnimationFrame sincroniza seu código com a renderização do navegador</strong>, tornando-o essencial para animações e atualizações visuais eficientes; <strong>(3) Compreender essa ordem de execução permite otimizar performance</strong>, evitar race conditions e escrever código previsível. Na prática, use Promises para lógica assíncrona crítica, setTimeout para atrasar execução, e rAF para qualquer coisa visual.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask" target="_blank" rel="noopener noreferrer">MDN: In depth: Microtasks and Macrotasks</a></li>
<li><a href="https://javascript.info/event-loop" target="_blank" rel="noopener noreferrer">JavaScript.info: Event Loop</a></li>
<li><a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model" target="_blank" rel="noopener noreferrer">HTML Standard: Event Loop Specification</a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame" target="_blank" rel="noopener noreferrer">MDN: requestAnimationFrame</a></li>
<li><a href="https://www.youtube.com/watch?v=cCOL7MC4Pl0" target="_blank" rel="noopener noreferrer">Jake Archibald: In The Loop (Video)</a></li>
</ul>