CAP 06 · LEC 03·Asincronía

async/await: código asíncrono que parece síncrono

async/await es azúcar sintáctica sobre Promises. No cambia cómo funciona el motor — solo cambia cómo lo escribes. El resultado es código asíncrono que se lee como código síncrono.

● INTERMEDIO10 min lectura5 ejerciciospor Fernando Herrera · actualizado mayo de 2026
¿Encontraste un error o algo que mejorar?Editá esta lección en GitHub →

async convierte cualquier función en una Promise

Añadir async delante de una función garantiza que siempre retorna una Promise, sin importar qué retorne adentro:

// Sin async — retorna el valor directamente function obtenerNombre() { return "Ana"; } console.log(obtenerNombre()); // "Ana" // Con async — retorna una Promise que envuelve el valor async function obtenerNombreAsync() { return "Ana"; } console.log(obtenerNombreAsync()); // Promise { 'Ana' } // Para acceder al valor, necesitas .then() o await obtenerNombreAsync().then(nombre => { console.log(nombre); // "Ana" }); // Una función async que lanza — retorna Promise rechazada async function fallar() { throw new Error("Algo salió mal"); } fallar().catch(err => console.error(err.message)); // Algo salió mal
// Sin async — retorna el valor directamente function obtenerNombre(): string { return "Ana"; } console.log(obtenerNombre()); // "Ana" // Con async — retorna una Promise que envuelve el valor async function obtenerNombreAsync(): Promise<string> { return "Ana"; } console.log(obtenerNombreAsync()); // Promise { 'Ana' } // Para acceder al valor, necesitas .then() o await obtenerNombreAsync().then((nombre: string) => { console.log(nombre); // "Ana" }); // Una función async que lanza — retorna Promise rechazada async function fallar(): Promise<never> { throw new Error("Algo salió mal"); } fallar().catch((err: Error) => console.error(err.message)); // Algo salió mal
Salida"Ana" Promise { 'Ana' } Ana Algo salió mal

await pausa hasta que la Promise resuelve

await solo puede usarse dentro de funciones async. Pausa la ejecución de esa función hasta que la Promise completa:

function esperar(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } function simularApi(endpoint) { return new Promise((resolve, reject) => { setTimeout(() => { if (endpoint === "/usuarios") { resolve(["Ana", "Pedro", "María"]); } else { reject(new Error(`Endpoint desconocido: ${endpoint}`)); } }, 300); }); } async function cargarUsuarios() { console.log("Iniciando carga..."); await esperar(100); // pausa real de 100ms const usuarios = await simularApi("/usuarios"); console.log("Usuarios:", usuarios); const total = usuarios.length; console.log("Total:", total); return total; } cargarUsuarios().then(total => { console.log("Función completada, total:", total); });
function esperar(ms: number): Promise<void> { return new Promise(resolve => setTimeout(resolve, ms)); } function simularApi(endpoint: string): Promise<string[]> { return new Promise((resolve, reject) => { setTimeout(() => { if (endpoint === "/usuarios") { resolve(["Ana", "Pedro", "María"]); } else { reject(new Error(`Endpoint desconocido: ${endpoint}`)); } }, 300); }); } async function cargarUsuarios(): Promise<number> { console.log("Iniciando carga..."); await esperar(100); const usuarios: string[] = await simularApi("/usuarios"); console.log("Usuarios:", usuarios); const total = usuarios.length; console.log("Total:", total); return total; } cargarUsuarios().then((total: number) => { console.log("Función completada, total:", total); });
SalidaIniciando carga... Usuarios: ["Ana", "Pedro", "María"] Total: 3 Función completada, total: 3

Manejo de errores con try/catch

Los errores de Promises rechazadas se capturan con try/catch — igual que los errores síncronos:

function buscarProducto(id) { return new Promise((resolve, reject) => { setTimeout(() => { const productos = { 1: "Laptop", 2: "Mouse" }; const producto = productos[id]; if (!producto) { reject(new Error(`Producto ${id} no encontrado`)); } else { resolve({ id, nombre: producto }); } }, 200); }); } async function mostrarProducto(id) { try { const producto = await buscarProducto(id); console.log("Encontrado:", producto.nombre); } catch (err) { console.error("Error al buscar:", err.message); } finally { console.log("Búsqueda completada"); } } mostrarProducto(1); // Encontrado: Laptop // Búsqueda completada mostrarProducto(99); // Error al buscar: Producto 99 no encontrado // Búsqueda completada
type Producto = { id: number; nombre: string }; function buscarProducto(id: number): Promise<Producto> { return new Promise((resolve, reject) => { setTimeout(() => { const productos: Record<number, string> = { 1: "Laptop", 2: "Mouse" }; const nombre = productos[id]; if (!nombre) { reject(new Error(`Producto ${id} no encontrado`)); } else { resolve({ id, nombre }); } }, 200); }); } async function mostrarProducto(id: number): Promise<void> { try { const producto = await buscarProducto(id); console.log("Encontrado:", producto.nombre); } catch (err) { if (err instanceof Error) { console.error("Error al buscar:", err.message); } } finally { console.log("Búsqueda completada"); } } mostrarProducto(1); // Encontrado: Laptop // Búsqueda completada mostrarProducto(99); // Error al buscar: Producto 99 no encontrado // Búsqueda completada
SalidaEncontrado: Laptop Búsqueda completada Error al buscar: Producto 99 no encontrado Búsqueda completada
No olvides el try/catch

Una función async sin try/catch que lanza un error produce una Promise rechazada no capturada. En Node.js esto termina el proceso. En el browser, muestra una advertencia en consola.

Promise.then() vs async/await

Son equivalentes — async/await es solo una forma diferente de escribir el mismo código:

AspectoPromise .then()async / await
LegibilidadCallbacks anidados en .then()Flujo lineal de arriba a abajo
Manejo de errores.catch() al final de la cadenatry/catch estándar
Variables intermediasHay que pasar por el scope del .then()Variables locales normales
DepuraciónBreakpoints en callbacks son confusosStep-through normal como código síncrono
ResultadoIdéntico en ambos casosIdéntico en ambos casos
function obtenerDatos(id) { return Promise.resolve({ id, valor: id * 10 }); } // Con .then() — todo en callbacks function procesarConThen(id) { return obtenerDatos(id) .then(datos => { const doble = datos.valor * 2; return obtenerDatos(doble); }) .then(datosFinal => { return `ID: ${datosFinal.id}, valor: ${datosFinal.valor}`; }); } // Con async/await — flujo lineal async function procesarConAwait(id) { const datos = await obtenerDatos(id); const doble = datos.valor * 2; const datosFinal = await obtenerDatos(doble); return `ID: ${datosFinal.id}, valor: ${datosFinal.valor}`; } procesarConAwait(3).then(console.log); // ID: 60, valor: 600
type Datos = { id: number; valor: number }; function obtenerDatos(id: number): Promise<Datos> { return Promise.resolve({ id, valor: id * 10 }); } // Con .then() — todo en callbacks function procesarConThen(id: number): Promise<string> { return obtenerDatos(id) .then((datos: Datos) => { const doble = datos.valor * 2; return obtenerDatos(doble); }) .then((datosFinal: Datos) => { return `ID: ${datosFinal.id}, valor: ${datosFinal.valor}`; }); } // Con async/await — flujo lineal async function procesarConAwait(id: number): Promise<string> { const datos = await obtenerDatos(id); const doble = datos.valor * 2; const datosFinal = await obtenerDatos(doble); return `ID: ${datosFinal.id}, valor: ${datosFinal.valor}`; } procesarConAwait(3).then(console.log); // ID: 60, valor: 600
SalidaID: 60, valor: 600

Practica