Volver a JavaScript Básico
Promesas y Async/Await
JavaScript es de un solo hilo. Las promesas y async/await permiten manejar operaciones asíncronas de forma limpia.
Callbacks (la forma antigua)
// Callback hell — difícil de leer y mantener
obtenerUsuario(id, (err, usuario) => {
if (err) return manejarError(err);
obtenerPosts(usuario.id, (err, posts) => {
if (err) return manejarError(err);
renderizarPosts(posts);
});
});
Promesas
// Crear una promesa
const esperar = (ms) =>
new Promise((resolve) => setTimeout(resolve, ms));
// Consumir una promesa
fetch("https://api.ejemplo.com/usuarios")
.then(response => response.json())
.then(datos => console.log(datos))
.catch(error => console.error(error))
.finally(() => console.log("Terminado"));
Async / Await
async function obtenerUsuario(id) {
try {
const response = await fetch(`/api/usuarios/${id}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const usuario = await response.json();
return usuario;
} catch (error) {
console.error("Error al obtener usuario:", error);
throw error; // Relanzar para que el llamador lo maneje
}
}
Ejecución en Paralelo
// Secuencial (lento) — cada uno espera al anterior
const usuario = await obtenerUsuario(1); // 200ms
const posts = await obtenerPosts(1); // 200ms
// Total: ~400ms
// Paralelo (rápido) — todos inician al mismo tiempo
const [usuario, posts] = await Promise.all([
obtenerUsuario(1),
obtenerPosts(1),
]);
// Total: ~200ms
Combinadores de Promesas
// Promise.all — esperar TODOS; falla si alguno falla
const resultados = await Promise.all([p1, p2, p3]);
// Promise.allSettled — esperar TODOS; nunca falla
const liquidadas = await Promise.allSettled([p1, p2, p3]);
liquidadas.forEach(({ status, value, reason }) => {
if (status === "fulfilled") console.log(value);
else console.error(reason);
});
// Promise.race — el primero en resolver gana
const primero = await Promise.race([lento, rapido, medio]);
// Promise.any — el primero en TENER ÉXITO gana (ES2021)
const exitoso = await Promise.any([p1, p2, p3]);
Iteración Asíncrona
async function* paginar(urlBase) {
let pagina = 1;
while (true) {
const datos = await fetch(`${urlBase}?pagina=${pagina}`).then(r => r.json());
if (datos.length === 0) return;
yield datos;
pagina++;
}
}
for await (const pagina of paginar("/api/posts")) {
console.log(pagina);
}
Regla de oro: Siempre maneja los rechazos de promesas — ya sea con
.catch()o un bloquetry/catchdentro de una funciónasync.