Skip to content

Capítulo 4.5: Async/await vs Promise

Tiempo de estudio: 30 minutos


1. Asincronía: Dos formas de gestionar la "comunicación espacial"

Imagina que el Centro de Control de Misiones (MCC) envía una orden a Marte. La respuesta tardará varios minutos en llegar. ¿Cómo organizar el trabajo durante ese tiempo?

Método 1: "Protocolo de devolución de llamada" (Promise con .then()) Envías una orden y das una instrucción: "CUANDO llegue la respuesta, ENTONCES ejecuta esta función". Esto se asemeja a una cadena de eventos.

Método 2: "Modo de espera" (Async/await) Dices: "Esperaré la respuesta a esta orden, pero no bloquearé otros paneles de control". Es como si pausaras la ejecución de esta tarea específica, permitiendo que el resto del MCC siga funcionando.

Ambos métodos resuelven la misma tarea: gestionar operaciones asíncronas. async/await es simplemente una sintaxis más moderna y legible que funciona "sobre" las promesas.

💡 Analogía espacial:

  • Promise con .then(): Es como escribir en un post-it: "Cuando el rover de Marte envíe una foto, pásala al departamento de análisis".
  • Async/await: Es como decirle a un asistente: "Espera la foto del rover de Marte, mientras yo me ocupo de los cálculos para el lanzamiento de un nuevo cohete".

2. Promise con .then(): Cadena de comandos clásica

Esta es la forma fundamental de trabajar con la asincronía en JavaScript, que utilizamos en el capítulo 4.1.

Recordemos nuestro primer código:

function getIssPositionWithPromises() {
    console.log('Enviando solicitud mediante el protocolo "Promise"...');

    fetch('http://api.open-notify.org/iss-now.json')
        .then(response => {
            // Etapa 1: Respuesta recibida
            if (!response.ok) {
                throw new Error(`Error HTTP: ${response.status}`);
            }
            return response.json(); // Devolvemos una nueva promesa
        })
        .then(data => {
            // Etapa 2: Datos parseados
            console.log('Datos recibidos mediante el protocolo "Promise":', data.iss_position);
        })
        .catch(error => {
            // Etapa 3 (Error): Algo salió mal en alguna de las etapas
            console.error('Fallo de comunicación mediante el protocolo "Promise":', error);
        });

    console.log('...comando enviado, el MCC sigue trabajando...');
}

Ventajas:

  • Cadena de acciones explícita.
  • Adecuado para operaciones secuenciales simples.

Desventajas:

  • "Infierno de las devoluciones de llamada" (Callback Hell): Con un gran número de operaciones asíncronas anidadas, el código puede convertirse en una "escalera" de .then() difícil de leer.
  • El manejo de errores puede ser menos intuitivo.

3. Async/await: Estilo síncrono moderno

async/await es "azúcar sintáctico" sobre las promesas, que permite escribir código asíncrono como si fuera síncrono.

Reglas de uso:

  1. La palabra clave await solo se puede usar dentro de una función marcada como async.
  2. await se coloca antes de una llamada que devuelve una promesa (por ejemplo, fetch() o response.json()).
  3. await "pausa" la ejecución de la función async hasta que la promesa se resuelva y devuelve su resultado.

El mismo código, reescrito con async/await:

async function getIssPositionWithAsyncAwait() {
    console.log('Enviando solicitud mediante el protocolo "Async/await"...');

    try {
        // Etapa 1: Esperamos la respuesta del servidor
        const response = await fetch('http://api.open-notify.org/iss-now.json');

        if (!response.ok) {
            throw new Error(`Error HTTP: ${response.status}`);
        }

        // Etapa 2: Esperamos a que el cuerpo de la respuesta se convierta a JSON
        const data = await response.json();

        console.log('Datos recibidos mediante el protocolo "Async/await":', data.iss_position);
    } catch (error) {
        // Etapa 3 (Error): Capturamos cualquier error del bloque try
        console.error('Fallo de comunicación mediante el protocolo "Async/await":', error);
    }

    console.log('...comando enviado, el MCC sigue trabajando...');
}

Ventajas:

  • Legibilidad: El código se ve casi como código síncrono normal, es fácil de leer de arriba abajo.
  • Manejo de errores: Se utiliza el bloque try...catch estándar y familiar.
  • Depuración: Es mucho más fácil de depurar, ya que se pueden establecer puntos de interrupción (breakpoints) en cada línea con await.

Desventajas:

  • Es fácil olvidar await o async, lo que provocará errores.

4. ¿Cuándo usar qué protocolo?

Situación Enfoque recomendado ¿Por qué?
La mayoría de los casos async/await El código es más limpio, más fácil de leer y depurar. Es el estándar moderno.
Cadena simple de 1-2 acciones Promise con .then() Funciona bien, el código sigue siendo compacto.
Ejecución paralela de múltiples solicitudes Promise.all() Este método permite ejecutar varias promesas simultáneamente y esperar a que todas se completen. async/await se combina perfectamente con él.

Ejemplo con Promise.all():

async function getParallelData() {
    try {
        // Iniciamos ambas solicitudes simultáneamente
        const [shipsResponse, launchesResponse] = await Promise.all([
            fetch('https://api.spacexdata.com/v4/rockets'),
            fetch('https://api.spacexdata.com/v4/launches/latest')
        ]);

        if (!shipsResponse.ok || !launchesResponse.ok) {
            throw new Error('¡Una de las solicitudes falló!');
        }

        const rockets = await shipsResponse.json();
        const latestLaunch = await launchesResponse.json();

        console.log(`Total de cohetes en la flota: ${rockets.length}`);
        console.log(`Último lanzamiento: ${latestLaunch.name}`);
    } catch (error) {
        console.error('Error al obtener datos paralelos:', error);
    }
}


Cuestionario de refuerzo

1. `async/await` es...

2. ¿Qué palabra clave es obligatoria para una función dentro de la cual se utiliza `await`?

3. La principal ventaja de `async/await` sobre `.then()`:

4. ¿Qué ocurrirá si se olvida `await` antes de `fetch()` dentro de una función `async`?

5. `Promise.all()` se utiliza para:


🚀 Resumen del capítulo:

Has aprendido dos sintaxis para gestionar operaciones asíncronas y entendido por qué async/await es la preferida en la mayoría de los proyectos modernos.

  • 🔗 Has refrescado tus conocimientos sobre Promise con .then().
  • 🛠️ Has comprendido en profundidad cómo funciona async/await y sus ventajas.
  • ⚡ Has aprendido sobre Promise.all para ejecutar peticiones paralelas.

¡Protocolos de comunicación aprendidos! En el capítulo final de esta sección, uniremos todos nuestros conocimientos y construiremos nuestro "Centro de Control de Vuelo", creando una interfaz completa para todas las operaciones CRUD.

📌 Práctica:

  • Reescribe todas las funciones en tu app.js que aún utilizan .then() al sintaxis async/await.
  • Intenta añadir otra petición en Promise.all() (por ejemplo, a https://api.spacexdata.com/v4/starlink) y muestra los datos.

⚠️ Si hay errores:

  • await is only valid in async functions: Asegúrate de que la función donde utilizas await esté marcada como async.
  • La variable contiene [object Promise]: Has olvidado poner await delante de la función que devuelve una promesa. ```