Aula 17 - Programação Assíncrona Avançada e Event Loop ⚡
Objetivo Pedagógico
Objetivo: Compreensão da arquitetura de concorrência do JavaScript no V8, funcionamento do Event Loop, Call Stack, Microtasks (Promises) e Macrotasks (Timers/I/O).
📑 1. Fundamentos Teóricos & Análise Técnica
O modelo de execução do JavaScript é estritamente single-threaded e baseado em um laço de eventos cooperativo (Event Loop). Embora o código do usuário seja executado em uma única thread principal, o ambiente hospedeiro (como o navegador ou o Node.js) fornece APIs assíncronas (Web APIs) que executam operações de I/O, timers e rede em threads de background do sistema operacional.
A ordem de prioridade de execução do Event Loop é governada por filas distintas: 1. Call Stack (Pilha de Chamadas): Executa frames síncronos de funções até seu esvaziamento completo. 2. Fila de Microtarefas (Microtask Queue): Processa callbacks de Promise.then/catch/finally, queueMicrotask() e MutationObserver. Crucial: O Event Loop drenará todas as microtarefas pendentes antes de prosseguir para qualquer outra operação. 3. Fila de Macrotarefas (Task Queue): Processa eventos disparados por setTimeout, setInterval, setImmediate e eventos de I/O do usuário. 4. Render Queue (Fase de Renderização): Oportunidade em que o navegador recalcula estilo, layout e pintura (tipicamente a cada 16.6ms para 60fps), ocorrendo após as microtarefas e antes de novas macrotarefas.
📐 Arquitetura Conceitual & Diagrama de Fluxo
flowchart TD
Stack["1. Call Stack (Síncrono)"] -->|Esvaziou| Micro["2. Microtask Queue<br>(Promises, queueMicrotask)"]
Micro -->|Drena Todas as Tarefas| Render["3. Pipeline de Renderização<br>(requestAnimationFrame, Layout, Paint)"]
Render --> Macro["4. Macrotask Queue<br>(setTimeout, I/O, Eventos DOM)"]
Macro --> Stack
style Stack fill:#e3f2fd,stroke:#1565c0
style Micro fill:#fff3e0,stroke:#e65100
style Render fill:#e8f5e9,stroke:#2e7d32
style Macro fill:#f3e5f5,stroke:#7b1fa2 🔍 Pilares e Diretrizes Técnicas
Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Esvaziamento Prioritário de Microtasks: Promises possuem prioridade absoluta sobre timers, garantindo resposta rápida a resoluções assíncronas. - Não-Bloqueio da Thread Principal: Operações computacionalmente intensivas devem ser quebradas com scheduler.yield() ou descarregadas para Web Workers. - Ordem de Resolução de Erros: Tratamento seguro de rejeições assíncronas não tratadas (unhandled promise rejections). - AbortController e Cancelamento: Uso de sinais de aborto para cancelar requisições fetch obsoletas em transições de tela.
🛠️ 2. Implementação Prática em JavaScript Assíncrono e Event Loop
Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:
// event-loop-concurrency.js (Demonstração e Controle de Filas)
// Demonstração da ordem determinística do Event Loop
console.log('1. [Sync] Início síncrono');
setTimeout(() => {
console.log('4. [Macrotask] Callback do setTimeout');
}, 0);
Promise.resolve().then(() => {
console.log('2. [Microtask] Resolução da Promise');
}).then(() => {
console.log('3. [Microtask] Encadeamento da Promise');
});
queueMicrotask(() => {
console.log('2b. [Microtask] Callback via queueMicrotask');
});
console.log('1b. [Sync] Fim síncrono');
// Saída: 1, 1b -> 2, 2b, 3 -> 4
💡 Análise Passo a Passo do Código
- Fase Síncrona: As linhas síncronas são empilhadas na Call Stack e executadas imediatamente ('1' e '1b').
- Fase de Microtarefas: Antes de olhar para o
setTimeout, o motor drena as Promises e oqueueMicrotask('2', '2b' e '3'). - Fase de Macrotarefas: Por fim, o timer com delay zero é retirado da Task Queue e executado ('4').
🎯 3. Próximos Passos & Sequência Didática
-
Slides da Aula
-
Quiz de Fixação
-
Exercícios Práticos
-
Desafio de Projeto