JavaScript e concorrência: threads, goroutines e async/await sem dor de cabeça

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Uma thread para governar todas: mitos e verdades sobre concorrência em JavaScript

\n\n

Há muito tempo, na era dos sites estáticos e botões "Enviar" que bloqueavam toda a interface, o JavaScript vivia feliz em uma única thread. Era suficiente: a requisição chegava, era executada, a requisição ia embora, a interface congelava. Mas os tempos mudaram. Hoje, esperamos que as aplicações web reajam instantaneamente: a rolagem não deve travar, as animações devem ser suaves e o carregamento de dados, imperceptível. E é aí que a concorrência entra em jogo.

\n\n

Muitos desenvolvedores confundem concorrência (concurrency) com paralelismo (parallelism). Em JavaScript, especialmente no navegador, lidamos mais com o primeiro. É como um malabarista: ele não segura todas as bolas no ar ao mesmo tempo (isso é paralelismo), mas alterna entre elas com tanta habilidade que cria a ilusão de simultaneidade. Neste artigo, vamos explorar três ferramentas-chave para organizar a concorrência em JS: async/await, goroutines (através de geradores e Web Workers) e threads clássicas. Vamos nessa!

\n\n

Async/Await: código assíncrono elegante

\n\n

async/await é um açúcar sintático sobre Promises, que surgiu no ES2017. Ele não torna o código multi-thread, mas o torna assíncrono. Quando você escreve await, o JavaScript "adormece" nessa função, liberando a thread para outras tarefas. Assim que a Promise é resolvida, a função "acorda" e continua a execução. É a ferramenta ideal para operações de I/O: requisições a APIs, leitura de arquivos, timers.

\n\n

Exemplo simples: carregando dados do servidor

\n\n
// Função que retorna uma Promise\nfunction fetchUser(id) {\n    return new Promise((resolve) => {\n        setTimeout(() => resolve({ id, name: 'Alexei' }), 1000);\n    });\n}\n\n// Função assíncrona\nasync function loadUserProfile(userId) {\n    console.log('Iniciando carregamento...');\n    const user = await fetchUser(userId);\n    console.log('Usuário carregado:', user.name);\n    return user;\n}\n\nloadUserProfile(42);\nconsole.log('Este código será executado imediatamente, sem esperar o carregamento!');\n
\n\n

Observe: console.log('Este código será executado imediatamente...') será executado antes de console.log('Usuário carregado'). A thread não é bloqueada — isso é concorrência em ação.

\n\n

Tratamento de erros

\n\n
async function fetchWithRetry(url, retries = 3) {\n    for (let i = 0; i < retries; i++) {\n        try {\n            const response = await fetch(url);\n            if (!response.ok) throw new Error('Erro HTTP');\n            return await response.json();\n        } catch (error) {\n            if (i === retries - 1) throw error;\n            console.log(`Tentativa ${i + 1} falhou, tentando novamente...`);\n        }\n    }\n}\n
\n\n

Quando usar: qualquer operação com recursos externos (API, bancos de dados, sistema de arquivos no Node.js). async/await é sua principal ferramenta para código assíncrono.

\n\n

Goroutines em JavaScript: mito ou realidade?

\n\n

O termo "goroutine" veio do Go e se refere a uma thread de execução leve. Em JavaScript, não há goroutines nativas, mas existem geradores (Generator Functions) e Web Workers, que podem simular um comportamento semelhante. Geradores permitem pausar e retomar a execução de uma função, dando controle sobre o fluxo de execução.

\n\n

Geradores como base da concorrência

\n\n
function* taskGenerator() {\n    console.log('Iniciando tarefa 1');\n    yield 'Tarefa 1 concluída';\n    console.log('Iniciando tarefa 2');\n    yield 'Tarefa 2 concluída';\n    console.log('Iniciando tarefa 3');\n    yield 'Tarefa 3 concluída';\n}\n\nconst iterator = taskGenerator();\nconsole.log(iterator.next().value); // Executa tarefa 1\n// Neste momento, podemos fazer outra coisa\nconsole.log(iterator.next().value); // Executa tarefa 2\nconsol                

Blogs

Book Recommendations