Concorrência e Multithreading em TypeScript: Nível Avançado
\n\nNo desenvolvimento web moderno e na programação de servidores, o desempenho e a capacidade de resposta das aplicações são criticamente importantes. O TypeScript, sendo uma extensão do JavaScript, herdou seu modelo de execução single-thread (Event Loop). No entanto, para resolver tarefas que consomem muitos recursos (processamento de imagens, criptografia, cálculos complexos), apenas a assincronia não é suficiente. Em um nível avançado, o desenvolvedor precisa entender como organizar o verdadeiro multithreading e o trabalho seguro com memória compartilhada. Neste artigo, analisaremos os principais mecanismos: Web Workers (navegador), Worker Threads (Node.js), SharedArrayBuffer e Atomics.
\n\n1. Web Workers: Paralelismo no Navegador
\n\nWeb Workers são a principal forma de executar código em uma thread separada no ambiente do navegador. O Worker não tem acesso ao DOM, mas pode realizar cálculos pesados sem bloquear a thread principal (UI).
\n\nCriar um Worker em TypeScript requer a compilação de um arquivo separado. Vamos considerar um exemplo: cálculo de grandes números de Fibonacci.
\n\nArquivo worker.ts (compilado para worker.js):
\n// worker.ts\nself.onmessage = (event: MessageEvent<number>) => {\n const n = event.data;\n const fib = (num: number): number => {\n if (num <= 1) return num;\n return fib(num - 1) + fib(num - 2);\n };\n const result = fib(n);\n self.postMessage(result);\n};\n\nArquivo main.ts:
\n// main.ts\nconst worker = new Worker(new URL('./worker.js', import.meta.url));\n\nworker.postMessage(40);\n\nworker.onmessage = (event: MessageEvent<number>) => {\n console.log(`Resultado: ${event.data}`); // Exibe após a conclusão\n worker.terminate();\n};\n\nworker.onerror = (error) => {\n console.error('Erro no Worker:', error.message);\n};\n\nNuances importantes:
\n- \n
- O Worker é executado em uma thread separada, mas não tem acesso às variáveis globais da thread principal. \n
- A transferência de dados ocorre por cópia (clonagem estrutural). Para dados grandes, use Transferable objects (por exemplo, ArrayBuffer). \n
- Para TypeScript, é obrigatório especificar os tipos nas mensagens para evitar erros em tempo de execução. \n
2. Worker Threads: Multithreading no Node.js
\n\nPara o ambiente de servidor Node.js, o análogo dos Web Workers é o módulo worker_threads. Ele permite criar threads isoladas com memória própria (isolado V8). Isso é ideal para operações intensivas de CPU, como hash ou parsing de JSON.
Exemplo: Criando um Worker para hash de senha (worker.ts):
\n// crypto-worker.ts\nimport { parentPort, workerData } from 'worker_threads';\nimport { createHash } from 'crypto';\n\nif (parentPort) {\n const { password, salt } = workerData;\n const hash = createHash('sha256')\n .update(password + salt)\n .digest('hex');\n parentPort.postMessage(hash);\n}\n\nArquivo principal (main.ts):
\n// main.ts\nimport { Worker } from 'worker_threads';\nimport path from 'path';\n\nfunction hashPassword(password: string, salt: string): Promise<string> {\n return new Promise((resolve, reject) => {\n const worker = new Worker(path.resolve(__dirname, 'crypto-worker.js'), {\n workerData: { password, salt }\n });\n\n worker.on('message', resolve);\n worker.on('error', reject);\n worker.on('exit', (code) => {\n if (code !== 0) reject(new Error(`Worker finalizou com código ${code}`));\n });\n });\n}\n\n(async () => {\n const hash = await hashPassword('mySecret', 'randomSalt');\n console.log(`Hash: ${hash}`);\n})();\n\nPrincipais diferenças dos Web Workers:
\n- \n
- Funciona no Node.js, com acesso ao sistema de arquivos e ao processo. \n
- Transferência de dados através de