Aprender JavaScript Programación asíncrona

Módulo del curso de JavaScript

JavaScript
JavaScript
Módulo del curso
9 lecciones
12 ejercicios
Actualizado: 30/06/2025

Módulo: Programación asíncrona

Este módulo forma parte del curso de JavaScript. Incluye 9 lecciones y 12 ejercicios de programación .

Programación asíncrona en JavaScript

La programación asíncrona representa uno de los paradigmas más importantes en JavaScript moderno. A diferencia de la programación síncrona tradicional, donde cada operación debe completarse antes de continuar con la siguiente, la programación asíncrona permite que el código continúe ejecutándose mientras esperamos que se completen operaciones que pueden tomar tiempo.

El problema de las operaciones bloqueantes

En JavaScript, muchas operaciones requieren tiempo para completarse: peticiones HTTP, lectura de archivos, consultas a bases de datos o temporizadores. Si estas operaciones fueran síncronas, bloquearían completamente la ejecución del programa hasta completarse.

// Ejemplo de operación que toma tiempo
console.log("Inicio");
// Imagina que esta operación tarda 3 segundos
realizarPeticionHTTP();
console.log("Fin"); // Se ejecutaría después de 3 segundos

JavaScript resuelve este problema mediante su modelo de concurrencia basado en un bucle de eventos (event loop) que permite manejar múltiples operaciones de forma no bloqueante.

Callbacks: la base de la asincronía

Los callbacks fueron la primera solución para manejar operaciones asíncronas en JavaScript. Un callback es una función que se pasa como argumento a otra función y se ejecuta cuando la operación asíncrona se completa.

function obtenerDatos(callback) {
    setTimeout(() => {
        const datos = { id: 1, nombre: "Usuario" };
        callback(datos);
    }, 2000);
}

obtenerDatos((resultado) => {
    console.log("Datos recibidos:", resultado);
});

Sin embargo, cuando necesitamos realizar múltiples operaciones asíncronas secuenciales, los callbacks pueden crear el temido "callback hell":

obtenerUsuario(id, (usuario) => {
    obtenerPedidos(usuario.id, (pedidos) => {
        obtenerDetalles(pedidos[0].id, (detalles) => {
            // Código anidado difícil de mantener
        });
    });
});

Promises: una solución más elegante

Las Promises introducen una forma más limpia de manejar operaciones asíncronas. Una Promise representa un valor que puede estar disponible ahora, en el futuro, o nunca.

function obtenerDatos() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const exito = Math.random() > 0.5;
            if (exito) {
                resolve({ id: 1, nombre: "Usuario" });
            } else {
                reject(new Error("Error al obtener datos"));
            }
        }, 2000);
    });
}

Las Promises tienen tres estados posibles:

  • Pending: estado inicial, ni cumplida ni rechazada
  • Fulfilled: operación completada exitosamente
  • Rejected: operación falló

El encadenamiento de Promises permite escribir código asíncrono más legible:

obtenerUsuario(id)
    .then(usuario => obtenerPedidos(usuario.id))
    .then(pedidos => obtenerDetalles(pedidos[0].id))
    .then(detalles => console.log(detalles))
    .catch(error => console.error("Error:", error));

Async/Await: sintaxis moderna

La sintaxis async/await proporciona una forma aún más intuitiva de trabajar con código asíncrono, haciendo que parezca código síncrono:

async function procesarDatos() {
    try {
        const usuario = await obtenerUsuario(id);
        const pedidos = await obtenerPedidos(usuario.id);
        const detalles = await obtenerDetalles(pedidos[0].id);
        console.log(detalles);
    } catch (error) {
        console.error("Error:", error);
    }
}

Una función marcada con async siempre retorna una Promise, y la palabra clave await pausa la ejecución hasta que la Promise se resuelve.

Manejo de múltiples operaciones asíncronas

JavaScript proporciona métodos útiles para manejar múltiples Promises simultáneamente:

Promise.all() ejecuta múltiples Promises en paralelo y espera a que todas se completen:

async function obtenerTodosLosDatos() {
    try {
        const [usuarios, productos, categorias] = await Promise.all([
            obtenerUsuarios(),
            obtenerProductos(),
            obtenerCategorias()
        ]);
        return { usuarios, productos, categorias };
    } catch (error) {
        console.error("Error en alguna operación:", error);
    }
}

Promise.race() retorna el resultado de la primera Promise que se resuelve:

const timeoutPromise = new Promise((_, reject) => 
    setTimeout(() => reject(new Error("Timeout")), 5000)
);

Promise.race([obtenerDatos(), timeoutPromise])
    .then(resultado => console.log(resultado))
    .catch(error => console.error(error));

Patrones comunes en programación asíncrona

El patrón de retry permite reintentar operaciones que pueden fallar:

async function operacionConReintentos(maxIntentos = 3) {
    for (let intento = 1; intento <= maxIntentos; intento++) {
        try {
            return await operacionQuePodriaFallar();
        } catch (error) {
            if (intento === maxIntentos) throw error;
            await esperar(1000 * intento); // Espera progresiva
        }
    }
}

La limitación de concurrencia evita sobrecargar recursos:

async function procesarEnLotes(items, tamañoLote = 5) {
    const resultados = [];
    
    for (let i = 0; i < items.length; i += tamañoLote) {
        const lote = items.slice(i, i + tamañoLote);
        const resultadosLote = await Promise.all(
            lote.map(item => procesarItem(item))
        );
        resultados.push(...resultadosLote);
    }
    
    return resultados;
}

La programación asíncrona en JavaScript es fundamental para crear aplicaciones responsivas y eficientes. Dominar estos conceptos permite escribir código que maneja operaciones complejas sin bloquear la interfaz de usuario, proporcionando una mejor experiencia al usuario final.

Lecciones de este módulo

Explora todas las lecciones disponibles en Programación asíncrona

Todos los módulos del curso

Navega entre los módulos de JavaScript

Explora más sobre JavaScript

Descubre más recursos de JavaScript

Alan Sastre - Autor del curso

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, JavaScript es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.