Introdução: por que seu site "trava" e quem é o culpado
\n\nImagine um restaurante onde um único garçom recebe pedidos, serve comida, lava louça e conta o dinheiro ao mesmo tempo. Caos, certo? É mais ou menos assim que o JavaScript single-thread funciona, se não gerenciarmos as tarefas corretamente. Quando escrevemos código que faz tudo ao mesmo tempo — carrega dados, processa cliques, desenha animações — o navegador congela e o usuário vê uma interface "pensativa".
\n\nHoje vamos entender como as filas de tarefas em JavaScript ajudam a transformar esse caos em um sistema organizado. Você aprenderá como o Event Loop distribui prioridades, como as microtarefas diferem das macrotarefas e como as tarefas em segundo plano JavaScript permitem não bloquear a thread principal. No final, você encontrará exemplos práticos que podem ser implementados imediatamente no seu projeto.
\n\nComo funciona o Event Loop: o maestro da orquestra de tarefas
\n\nNo centro de toda assincronia está o Event Loop JavaScript. É um mecanismo que fica girando infinitamente e perguntando: "Há algo para executar? E microtarefas? E renderização?". Se você já se perguntou por que setTimeout não é executado imediatamente, enquanto Promise.then é quase instantâneo — a resposta está aqui.
Pilha de chamadas (Call Stack)
\nÉ o lugar onde as funções vão para execução imediata. Enquanto a pilha estiver ocupada, nada mais acontece. Se sua função calcula um milhão de números — o navegador congela, porque a pilha não será liberada.
\n\nFila de macrotarefas (Macrotask Queue)
\nAqui entram setTimeout, setInterval, eventos DOM (cliques, scroll), carregamento de recursos. O Event Loop pega uma tarefa desta fila, executa, depois verifica microtarefas, renderiza a página — e então pega a próxima macrotarefa.
Fila de microtarefas (Microtask Queue)
\nAqui é o reino de Promise, queueMicrotask, MutationObserver. As microtarefas têm a maior prioridade. Assim que a pilha esvazia, o Event Loop executa TODAS as microtarefas antes de passar para a próxima macrotarefa. É por isso que Promise.resolve().then() é executado mais rápido que setTimeout.
console.log('1');\n\nsetTimeout(() => {\n console.log('2');\n}, 0);\n\nPromise.resolve().then(() => {\n console.log('3');\n});\n\nconsole.log('4');\n\n// Saída: 1, 4, 3, 2\n\n\nEste exemplo é clássico. setTimeout (macrotarefa) é adiado, mesmo com atraso zero, enquanto Promise.then (microtarefa) é executado imediatamente após o código síncrono. Entender essa ordem é a chave para escrever código assíncrono previsível.
Tarefas em segundo plano: como não bloquear a interface
\n\nAgora, o principal problema: o que fazer quando é necessário executar um trabalho pesado (processamento de imagens, cálculos complexos, análise de dados)? Se executar isso na thread principal — a interface trava. A solução são as tarefas em segundo plano JavaScript.
\n\nWeb Workers — verdadeiro multithreading
\nWeb Workers JS permitem executar código em uma thread separada. Ele não tem acesso ao DOM, mas pode trocar mensagens com a thread principal. É a ferramenta ideal para processamento de filas JS em segundo plano.
\n\n// main.js\nconst worker = new Worker('worker.js');\n\nworker.postMessage({ data: [1, 2, 3, 4, 5, 6] });\n\nworker.onmessage = (event) => {\n console.log('Resultado do worker:', event.data);\n};\n\n// worker.js\nself.onmessage = (event) => {\n const numbers = event.data.data;\n // Trabalho pesado: filtrar números pares\n const result = numbers.filter(n => n % 2 === 0);\n self.postMessage(result);\n};\n\n\nObserve: a thread principal não é bloqueada. O usuário pode clicar, rolar, digitar texto — tudo funcionará suavemente enquanto o worker processa.
\n\n