Trabajo con colas de tareas en JavaScript en la práctica con Node.js

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

Introducción: ¿para qué sirven las colas de tareas en JavaScript?

\n

En el desarrollo web moderno con Node.js, a menudo surgen tareas que no pueden ejecutarse instantáneamente dentro de una única solicitud HTTP. Envío de correos electrónicos masivos, generación de informes PDF, procesamiento de imágenes, sincronización con API externas: todas estas operaciones requieren tiempo y recursos. Si se ejecutan de forma síncrona, el usuario esperará demasiado tiempo por la respuesta y el servidor podría sobrecargarse.

\n

Las colas de tareas (Job Queues) resuelven este problema. Permiten aplazar la ejecución de operaciones pesadas, distribuir la carga, garantizar el reprocesamiento en caso de fallos y escalar el sistema horizontalmente. En este artículo, analizaremos los aspectos prácticos del trabajo con colas en JavaScript (Node.js): desde la teoría hasta la escritura de código funcional utilizando bibliotecas populares.

\n\n

Conceptos básicos de las colas de tareas

\n

Antes de pasar al código, es importante comprender los elementos clave de cualquier cola de tareas:

\n
    \n
  • Job (tarea) — unidad de trabajo que debe ejecutarse. Generalmente contiene datos (payload) e metainformación (prioridad, intentos, estado).
  • \n
  • Queue (cola) — estructura de datos (a menudo basada en Redis) que almacena las tareas en orden de llegada.
  • \n
  • Worker (trabajador) — proceso o hilo que toma las tareas de la cola y las ejecuta.
  • \n
  • Producer (productor) — parte del sistema que añade tareas a la cola.
  • \n
  • Consumer (consumidor) — sinónimo de trabajador, que procesa las tareas.
  • \n
\n

En Node.js, las bibliotecas más populares para trabajar con colas son Bull y Kue. Ambas utilizan Redis como broker de mensajes. Bull es más moderna y eficiente, mientras que Kue es más sencilla para empezar. En este artículo nos centraremos en Bull, como la solución recomendada para producción.

\n\n

Implementación práctica de una cola con Bull

\n

Instalación y configuración

\n

Para empezar, instale Redis (localmente o mediante Docker) y añada la biblioteca al proyecto:

\n
npm install bull
\n

La inicialización básica de una cola se ve así:

\n
const Queue = require('bull');\nconst imageQueue = new Queue('image processing', {\n  redis: { host: 'localhost', port: 6379 }\n});
\n\n

Adición de tareas (Producer)

\n

El productor añade una tarea con datos y opciones:

\n
app.post('/upload', async (req, res) => {\n  const job = await imageQueue.add({\n    imageUrl: req.body.url,\n    userId: req.user.id\n  }, {\n    attempts: 3,        // número de intentos en caso de error\n    backoff: 5000,      // retardo entre intentos (ms)\n    removeOnComplete: true // eliminar la tarea tras éxito\n  });\n  res.json({ jobId: job.id });\n});
\n\n

Procesamiento de tareas (Worker)

\n

El trabajador es un proceso separado (o el mismo proceso, pero asíncrono) que escucha la cola:

\n
imageQueue.process(async (job, done) => {\n  try {\n    const { imageUrl, userId } = job.data;\n    console.log(`Procesando imagen ${imageUrl} para el usuario ${userId}`);\n    // Aquí su lógica: descargar, redimensionar, guardar\n    await processImage(imageUrl);\n    done(); // señal de finalización exitosa\n  } catch (error) {\n    done(new Error('Error de procesamiento: ' + error.message));\n  }\n});
\n\n

Manejo de errores y reintentos

\n

Bull reintenta automáticamente la tarea si el trabajador finaliza con un error. Puede configurar la estrategia de reintentos:

\n
const job = await imageQueue.add(data, {\n  attempts: 5,\n  backoff: { type: 'exponential', delay: 2000 }\n});
\n

También puede escuchar eventos de la cola para monitoreo:

\n
imageQueue.on('completed', (job, result) => {\n  console.log(`Tarea ${job.id} completada`);\n});\nimageQueue.on('failed', (job, err) => {\n  console.error(`Tarea ${job.id} falló: ${err.message}`);\n});

Blogs

Book Recommendations