Async/await vs promesas en JavaScript

Clase 34 de 39Curso de Fundamentos de JavaScript

Resumen

Aprende a escribir código asíncrono en JavaScript más legible y mantenible con promesas, encadenamiento con then/catch y la azúcar sintáctica de async/await. Verás cómo una función utilitaria como esperar encapsula setTimeout para simular tareas que no bloquean la app, y cómo try/catch simplifica el manejo de errores.

¿Por qué encadenar promesas en JavaScript es más amigable?

Trabajar con promesas evita el caos de los callbacks anidados. El encadenamiento con then permite procesar resultados paso a paso y usar un único catch final para capturar fallos. Cuando una promesa está en estado rechazado, el error se propaga al catch y es más fácil de identificar.

¿Cómo se ve el encadenamiento con then y catch?

// Utilidad para simular espera sin bloquear
const esperar = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Funciones con promesas que reutilizan "esperar"
const obtenerUsuario = () => esperar(200).then(() => ({ id: 1, nombre: 'Usuario' }));
const obtenerNotas = (usuarioId) => esperar(200).then(() => ({ usuarioId, notas: [10, 9, 8] }));
const procesarNotas = ({ notas }) => esperar(200).then(() => ({ promedio: notas.reduce((a,b)=>a+b)/notas.length }));

// Encadenamiento legible con then/catch
obtenerUsuario()
  .then((usuario) => obtenerNotas(usuario.id))
  .then((data) => procesarNotas(data))
  .then((resultado) => console.log('Resultado:', resultado))
  .catch((error) => console.error('Error:', error));
  • Misma estructura de pasos: obtener usuario, obtener notas, procesar notas.
  • Un flujo claro: cada then recibe y entrega datos al siguiente.
  • Manejo de errores centralizado con catch final.

¿Cómo usar async y await para una sintaxis más limpia?

La azúcar sintáctica async/await encapsula la complejidad de las promesas para que el código se lea de forma secuencial. La palabra reservada async marca una función asíncrona y await espera su resultado sin bloquear el hilo principal. Con try/catch se captura cualquier error en un solo lugar.

¿Cuál es la estructura básica con async y await?

// Misma utilidad para tiempos de espera
const esperar = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Funciones asíncronas
async function obtenerUsuario() {
  await esperar(200);
  return { id: 1, nombre: 'Usuario' };
}

async function obtenerNotas(usuarioId) {
  await esperar(200);
  return { usuarioId, notas: [10, 9, 8] };
}

async function procesarNotas({ notas }) {
  await esperar(200);
  const promedio = notas.reduce((a, b) => a + b) / notas.length;
  return { promedio };
}

// Orquestación con try/catch
async function main() {
  try {
    const usuario = await obtenerUsuario();
    const data = await obtenerNotas(usuario.id);
    const resultado = await procesarNotas(data);
    console.log('Usuario:', usuario.nombre);
    console.log('Resultado:', resultado);
  } catch (error) {
    console.error('Error:', error); // Si una promesa se rechaza, cae aquí.
  }
}

main();
  • Lectura lineal: parece síncrono, pero no bloquea.
  • Menos ruido visual: sin anidar then.
  • Errores controlados con try/catch en un solo bloque.

¿Qué ventajas prácticas aporta al flujo de trabajo?

  • Legibilidad y mantenimiento superiores en flujos largos.
  • Encapsulamiento con una utilidad como esperar en lugar de repetir setTimeout.
  • Flujo no bloqueante: la app puede seguir ejecutando otras tareas.
  • Uso consistente de palabras reservadas: async, await, try, catch.

¿Qué habilidades y keywords aplicar al practicar asincronismo?

Practica con ejercicios: crea funciones que simulen llamadas a un API o a un archivo local usando promesas y luego refactoriza con async/await. Comparte tus resultados y debate mejoras.

  • Asincronismo en JavaScript: flujos que no bloquean la app.
  • Callbacks vs promesas: menos anidación, más claridad con then/catch.
  • Encadenamiento de promesas: varios then y un catch final.
  • Manejo de errores: catch en promesas y try/catch con async/await.
  • Función utilitaria: esperar para encapsular setTimeout.
  • Azúcar sintáctica: async/await para una sintaxis más legible.
  • Estados de una promesa: si está rechazada, el error se captura con catch.
  • Salida y depuración: uso de console.log para verificar resultados.

¿Tienes una variante de este flujo o un reto que te haya resultado interesante? Compártelo en los comentarios y cuéntanos cómo manejaste los errores y la legibilidad del código.