Node.js

Node

Tutorial Node: setTimeout, setInterval

Aprende a usar setTimeout y setInterval en Node.js para gestionar temporizadores y tareas asíncronas de forma eficiente.

Aprende Node y certifícate

setTimeout y setInterval

En el desarrollo de aplicaciones Node.js, frecuentemente necesitamos ejecutar código después de un tiempo determinado o repetir operaciones a intervalos regulares. JavaScript proporciona dos funciones globales fundamentales para el manejo temporal: setTimeout y setInterval. Estas funciones son especialmente útiles en Node.js para tareas como limpieza de recursos, monitoreo de sistemas, procesamiento por lotes y gestión de timeouts en operaciones asíncronas.

setTimeout: Ejecución diferida

La función setTimeout permite ejecutar una función después de un retraso específico medido en milisegundos. Esta función devuelve un identificador único que puede utilizarse para cancelar la ejecución si es necesario.

// Sintaxis básica
const timeoutId = setTimeout(callback, delay, ...args);

Veamos un ejemplo práctico de uso básico:

console.log('Inicio del programa');

setTimeout(() => {
    console.log('Este mensaje aparece después de 2 segundos');
}, 2000);

console.log('Este mensaje aparece inmediatamente');

// Salida:
// Inicio del programa
// Este mensaje aparece inmediatamente
// Este mensaje aparece después de 2 segundos

El comportamiento asíncrono de setTimeout permite que el código continúe ejecutándose sin bloquear el hilo principal. Esto es fundamental en Node.js, donde el rendimiento depende de mantener el event loop libre.

Pasando argumentos a la función callback

setTimeout permite pasar argumentos adicionales que se enviarán a la función callback:

function saludar(nombre, apellido) {
    console.log(`Hola ${nombre} ${apellido}`);
}

setTimeout(saludar, 1500, 'Juan', 'Pérez');
// Después de 1.5 segundos: "Hola Juan Pérez"

Cancelación de timeouts

Podemos cancelar un timeout antes de que se ejecute utilizando clearTimeout:

const timeoutId = setTimeout(() => {
    console.log('Este mensaje nunca aparecerá');
}, 3000);

// Cancelamos el timeout después de 1 segundo
setTimeout(() => {
    clearTimeout(timeoutId);
    console.log('Timeout cancelado');
}, 1000);

setInterval: Ejecución repetitiva

La función setInterval ejecuta una función repetidamente con un intervalo fijo entre cada ejecución:

// Sintaxis básica
const intervalId = setInterval(callback, delay, ...args);

Ejemplo de uso para crear un contador:

let contador = 0;

const intervalId = setInterval(() => {
    contador++;
    console.log(`Contador: ${contador}`);
    
    // Detenemos después de 5 iteraciones
    if (contador >= 5) {
        clearInterval(intervalId);
        console.log('Intervalo detenido');
    }
}, 1000);

Casos de uso prácticos

Monitoreo de recursos del sistema:

const os = require('os');

function mostrarEstadisticas() {
    const memoriaLibre = (os.freemem() / 1024 / 1024).toFixed(2);
    const cargaCPU = os.loadavg()[0].toFixed(2);
    
    console.log(`Memoria libre: ${memoriaLibre} MB`);
    console.log(`Carga CPU: ${cargaCPU}`);
    console.log('---');
}

// Mostrar estadísticas cada 5 segundos
const monitoreo = setInterval(mostrarEstadisticas, 5000);

// Detener monitoreo después de 30 segundos
setTimeout(() => {
    clearInterval(monitoreo);
    console.log('Monitoreo finalizado');
}, 30000);

Limpieza automática de archivos temporales:

const fs = require('fs');
const path = require('path');

function limpiarArchivosTemporales() {
    const directorioTemp = './temp';
    
    if (fs.existsSync(directorioTemp)) {
        const archivos = fs.readdirSync(directorioTemp);
        
        archivos.forEach(archivo => {
            const rutaCompleta = path.join(directorioTemp, archivo);
            const stats = fs.statSync(rutaCompleta);
            const tiempoTranscurrido = Date.now() - stats.mtime.getTime();
            
            // Eliminar archivos más antiguos de 1 hora
            if (tiempoTranscurrido > 3600000) {
                fs.unlinkSync(rutaCompleta);
                console.log(`Archivo eliminado: ${archivo}`);
            }
        });
    }
}

// Ejecutar limpieza cada 30 minutos
setInterval(limpiarArchivosTemporales, 30 * 60 * 1000);

Gestión de timeouts en operaciones HTTP

Una aplicación común es implementar timeouts personalizados para operaciones que pueden tardar demasiado:

const http = require('http');

function realizarPeticionConTimeout(url, timeoutMs = 5000) {
    return new Promise((resolve, reject) => {
        const peticion = http.get(url, (respuesta) => {
            let datos = '';
            
            respuesta.on('data', (chunk) => {
                datos += chunk;
            });
            
            respuesta.on('end', () => {
                clearTimeout(timeoutId);
                resolve(datos);
            });
        });
        
        // Configurar timeout personalizado
        const timeoutId = setTimeout(() => {
            peticion.destroy();
            reject(new Error(`Timeout: La petición tardó más de ${timeoutMs}ms`));
        }, timeoutMs);
        
        peticion.on('error', (error) => {
            clearTimeout(timeoutId);
            reject(error);
        });
    });
}

// Uso de la función
realizarPeticionConTimeout('http://httpbin.org/delay/3', 2000)
    .then(datos => console.log('Respuesta recibida'))
    .catch(error => console.error('Error:', error.message));

Consideraciones importantes

Al trabajar con setTimeout y setInterval en Node.js, es crucial recordar que estas funciones no garantizan una precisión exacta en los tiempos. El event loop puede estar ocupado procesando otras operaciones, lo que puede retrasar la ejecución.

Para aplicaciones que requieren alta precisión temporal, considera usar process.hrtime.bigint() para mediciones más exactas:

const inicioTiempo = process.hrtime.bigint();

setTimeout(() => {
    const tiempoTranscurrido = process.hrtime.bigint() - inicioTiempo;
    const milisegundos = Number(tiempoTranscurrido) / 1000000;
    
    console.log(`Tiempo real transcurrido: ${milisegundos.toFixed(2)}ms`);
}, 1000);

Siempre recuerda limpiar los timers cuando ya no los necesites para evitar memory leaks, especialmente en aplicaciones de larga duración. Esto es particularmente importante cuando trabajas con intervalos que pueden ejecutarse indefinidamente.

Aprende Node online

Otras lecciones de Node

Accede a todas las lecciones de Node y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Node y certifícate

Ejercicios de programación de Node

Evalúa tus conocimientos de esta lección setTimeout, setInterval con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.