Introducción: ¿por qué se necesitan colas de tareas en JavaScript?
\nEn el desarrollo web moderno, las aplicaciones a menudo se enfrentan a tareas que no pueden ejecutarse instantáneamente dentro de una sola solicitud HTTP. Enviar correos electrónicos, procesar imágenes, generar informes PDF o sincronizar con APIs externas: todo esto requiere tiempo y puede "colgar" el servidor si se ejecuta de forma síncrona.
\nLas colas de tareas (Task Queues) resuelven este problema. Permiten posponer la ejecución de operaciones que consumen muchos recursos y procesarlas de forma asíncrona en segundo plano. En este artículo, analizaremos cómo crear y gestionar colas de tareas en el entorno Node.js utilizando bibliotecas populares.
\n\n1. Fundamentos del trabajo con colas en Node.js
\nUna cola de tareas es una estructura de datos que funciona bajo el principio FIFO (First In, First Out). Las tareas se añaden al final de la cola y se procesan desde el principio. En el contexto de Node.js, esto significa que su servidor puede responder rápidamente al usuario ("Tarea aceptada para procesamiento"), y la tarea en sí se ejecutará más tarde.
\nPara trabajar con colas en Node.js, se utilizan bibliotecas especializadas que dependen de almacenamientos externos (generalmente Redis). Consideremos las dos más populares:
\n- \n
- Bull — una biblioteca moderna, rápida y estable basada en Redis. \n
- Kue — una biblioteca más antigua, pero aún popular, con una interfaz web integrada. \n
Nos centraremos en Bull, ya que es el estándar de facto para nuevos proyectos.
\n\n1.1 Instalación y configuración de Bull
\nPara empezar, instale las dependencias necesarias:
\nnpm install bull ioredis\nAhora creemos una cola simple:
\nconst Queue = require('bull');\nconst myQueue = new Queue('emailQueue', {\n redis: {\n host: '127.0.0.1',\n port: 6379\n }\n});\n\n// Añadimos una tarea a la cola\nmyQueue.add({\n to: 'user@example.com',\n subject: 'Correo de bienvenida',\n body: '¡Bienvenido a nuestro sitio web!'\n});\n\nconsole.log('Tarea añadida a la cola');\nEn este ejemplo, creamos una cola llamada emailQueue y añadimos una tarea: enviar un correo. La tarea aún no se ha ejecutado, solo está esperando a su procesador.
2. Procesamiento de tareas de la cola
\nPara que las tareas comiencen a ejecutarse, necesitamos un procesador (consumer). Este "escuchará" la cola y tomará las tareas para ejecutarlas.
\nCreemos un archivo worker.js:
const Queue = require('bull');\nconst emailQueue = new Queue('emailQueue', {\n redis: { host: '127.0.0.1', port: 6379 }\n});\n\n// Función procesadora\nemailQueue.process(async (job) => {\n const { to, subject, body } = job.data;\n console.log(`Enviando correo a ${to}...`);\n \n // Simulación de envío de correo (en un proyecto real aquí iría nodemailer)\n await new Promise(resolve => setTimeout(resolve, 2000));\n \n console.log(`Correo "${subject}" enviado a ${to}`);\n return { status: 'sent', email: to };\n});\n\nconsole.log('Procesador iniciado y esperando tareas...');\nEjecute este script y luego añada una tarea del primer ejemplo. Verá cómo se procesa la tarea.
\n\n2.1 Manejo de errores y reintentos
\nEn proyectos reales, las tareas pueden fallar (por ejemplo, el servidor SMTP no está disponible). Bull proporciona un mecanismo de reintentos incorporado:
\nemailQueue.add(\n { to: 'user@example.com', subject: 'Correo importante' },\n { \n attempts: 5, // Número de intentos\n backoff: { type: 'exponential', delay: 2000 } // Retardo exponencial\n }\n);\n\n// En el procesador se puede manejar el fallo\nemailQueue.on('failed', (job, err) => {\n console.error(`La tarea ${job.id} falló: ${err.message}`);\n});\n\n3. Funcionalidades avanzadas de las colas
\nBull proporciona muchas funciones útiles para la gestión de tareas.
\n\n3.1 Prioridades de tareas
Blogs
Book Recommendations
Leer también
Monorepositorio con JavaScript: organización del código y mejores prácticas