Concurrencia y Multihilo en TypeScript: Guía Completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Concurrencia y subprocesos múltiples en TypeScript: de la teoría a la práctica



Las aplicaciones web modernas requieren alto rendimiento. TypeScript, que funciona sobre Node.js, proporciona herramientas potentes para procesar múltiples tareas simultáneamente. En este artículo, analizaremos cómo funcionan la concurrencia y el multithreading en TypeScript, y aprenderemos a aplicarlos en la práctica.



Concurrencia vs Paralelismo: diferencias clave



Antes de profundizar en el código, es importante entender la diferencia entre concurrencia y paralelismo.

  • Concurrencia — es la capacidad de un programa para procesar varias tareas, alternando entre ellas. En JavaScript/TypeScript, esto se implementa a través del Event Loop y operaciones asíncronas.
  • Paralelismo — es la ejecución simultánea de varias tareas en diferentes núcleos del procesador. En Node.js, esto se logra a través de Worker Threads.


TypeScript (al igual que JavaScript) es monohilo por naturaleza, pero gracias a la asincronía y a Worker Threads, podemos utilizar ambos enfoques de manera efectiva.



Asincronía: la base de la concurrencia en TypeScript



La programación asíncrona es el primer paso hacia la concurrencia. Veamos los mecanismos principales.



Promises y async/await



TypeScript moderno utiliza activamente async/await para trabajar con operaciones asíncronas. Esto permite escribir código que parece síncrono, pero se ejecuta de manera concurrente.



// Ejemplo de función asíncronaasync function fetchData(url: string): Promise<any> {  const response = await fetch(url);  return response.json();}

// Ejecución concurrente de múltiples solicitudesasync function fetchAllData(): Promise<void> { const [users, posts, comments] = await Promise.all([ fetchData('/api/users'), fetchData('/api/posts'), fetchData('/api/comments') ]); console.log('Todos los datos cargados concurrentemente');}


Promise.all permite ejecutar varias operaciones asíncronas simultáneamente, lo que acelera significativamente la ejecución en comparación con la ejecución secuencial.



Manejo de errores en código asíncrono



Es importante manejar correctamente los errores durante la ejecución concurrente:



async function safeFetchAll(): Promise<void> {  try {    const results = await Promise.allSettled([      fetchData('/api/users'),      fetchData('/api/invalid'),      fetchData('/api/posts')    ]);        results.forEach((result, index) => {      if (result.status === 'fulfilled') {        console.log(`Solicitud ${index} exitosa:`, result.value);      } else {        console.error(`Solicitud ${index} falló:`, result.reason);      }    });  } catch (error) {    console.error('Error crítico:', error);  }}


Worker Threads: verdadero multithreading en TypeScript



Para tareas intensivas en CPU (procesamiento de imágenes, cálculos complejos), la asincronía por sí sola no es suficiente. Aquí es donde entran en juego los Worker Threads — hilos de ejecución reales.



Creación de un Worker Thread



Veamos un ejemplo de cálculo de números de Fibonacci en un hilo separado:



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

function fibonacci(n: number): number { if (n <= 1) return n; return fibonacci(n - 1) + fibonacci(n - 2);}

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


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

function runFibonacci(n: number): Promise<number> { return new Promise((resolve, reject) => { const worker = new Worker(path.resolve(__dirname, 'fibonacci.worker.ts')); worker.postMessage(n); worker.on('message', (result: number) => { resolve(result); worker.terminate(); }); worker.on('er

Blogs

Book Recommendations