Concorrência e Multithreading em TypeScript: do A ao Z

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

Concorrência e Multithreading em TypeScript: do A ao Z

No mundo moderno do desenvolvimento web, a performance das aplicações está em primeiro plano. TypeScript, sendo uma extensão fortemente tipada sobre JavaScript, oferece aos desenvolvedores ferramentas poderosas para trabalhar com assincronicidade e multithreading. Neste artigo, abordaremos os conceitos fundamentais de concorrência, aprenderemos como o Event Loop funciona e como usar Worker Threads para verdadeiro multithreading em Node.js.



1. Assincronicidade e Event Loop: a base da concorrência em TypeScript

Antes de falar sobre multithreading, é importante entender como TypeScript (e JavaScript) processa tarefas concorrentes. Na base está o Event Loop — um mecanismo que permite executar operações de entrada e saída não bloqueantes, sem criar novas threads.

Vejamos um exemplo simples de código assíncrono:

async function fetchData(url: string): Promise<string> {    const response = await fetch(url);    return response.text();}

async function main(): Promise<void> { console.log('Início do carregamento'); const data = await fetchData('https://api.example.com/data'); console.log('Dados recebidos:', data);}

main();console.log('O código continua executando');

Neste exemplo, await não bloqueia a thread principal. Enquanto aguarda a resposta do servidor, o Event Loop continua processando outras tarefas, como a execução de console.log. Isso é concorrência — a capacidade de processar várias tarefas em um mesmo período de tempo, alternando entre elas.



2. Promises e async/await: gerenciamento de operações assíncronas

TypeScript oferece construções sintáticas convenientes para trabalhar com assincronicidade. Promises são objetos que representam o resultado futuro de uma operação assíncrona. A combinação async/await torna o código linear e legível.

Vejamos um cenário mais complexo — execução paralela de várias requisições:

async function loadMultipleUsers(userIds: number[]): Promise<User[]> {    const promises = userIds.map(id => fetch(`/users/${id}`).then(res => res.json()));    return Promise.all(promises);}

// Usoconst users = await loadMultipleUsers([1, 2, 3, 4, 5]);console.log(users); // Todos os usuários carregados em paralelo

O método Promise.all inicia todas as promises simultaneamente, o que acelera significativamente a execução em comparação com o carregamento sequencial. Este é um exemplo ideal de concorrência: as tarefas são executadas "simultaneamente" dentro de uma única thread.



3. Verdadeiro multithreading: Worker Threads em Node.js

Embora a assincronicidade lide bem com operações de entrada e saída, ela não ajuda em tarefas intensivas de CPU (processamento de imagens, cálculos complexos, criptografia). Para esses casos, Node.js oferece Worker Threads — threads reais do sistema operacional.

Vejamos um exemplo de cálculo de fatorial em uma thread separada:

// worker.tsimport { parentPort } from 'worker_threads';

function factorial(n: number): number { if (n === 0) return 1; return n * factorial(n - 1);}

parentPort?.on('message', (n: number) => { const result = factorial(n); parentPort?.postMessage(result);});

// main.tsimport { Worker } from 'worker_threads';

function runWorker(n: number): Promise<number> { return new Promise((resolve, reject) => { const worker = new Worker('./worker.ts'); worker.postMessage(n); worker.on('message', resolve); worker.on('error', reject); });}

async function main() { const result = await runWorker(20); console.log('Fatorial de 20:', result);}

main();

Cada Worker opera em sua própria thread, possui seu próprio Event Loop e é

Blogs

Book Recommendations