Cómo funcionan las Promesas en JavaScript: Guía paso a paso
Las Promesas son una de las herramientas más poderosas del JavaScript moderno. Gracias a ellas, podemos manejar operaciones asíncronas (como llamadas a APIs, acceso a archivos o temporizadores) de una forma mucho más legible y predecible que con los antiguos callbacks.
🌱 ¿Qué es una Promesa?
Una Promesa es un objeto que representa el resultado eventual de una operación asíncrona: puede cumplirse ( resolve) con éxito o rechazarse (reject) si ocurre un error.
Piensa en ella como un contrato:
“Te prometo que te daré una respuesta… no ahora, pero en algún momento.”
Estados de una Promesa
| Estado | Descripción | Emoji |
|---|---|---|
pending | La promesa está en proceso, esperando que termine la operación. | ⏳ |
fulfilled | La promesa se resolvió correctamente. | ✅ |
rejected | Algo salió mal. | ❌ |
⚙️ Crear una Promesa
Podemos crear una promesa usando el constructor Promise():
const miPromesa = new Promise((resolve, reject) => {
const exito = true;
if (exito) {
resolve("Operación completada con éxito 🎉");
} else {
reject("Algo salió mal 💥");
}
});
Consumir una Promesa
Para obtener el valor de la promesa, usamos los métodos .then() y .catch():
miPromesa
.then(resultado => console.log(resultado)) // 🎉 "Operación completada con éxito"
.catch(error => console.error(error)); // 💥 "Algo salió mal"
⛓️ Encadenar Promesas
Una de las mayores ventajas de las promesas es que permiten encadenar acciones asíncronas sin caer en el infame callback hell 😱.
obtenerUsuario()
.then(usuario => obtenerPedidos(usuario.id))
.then(pedidos => procesarPedidos(pedidos))
.then(resultado => console.log("Procesado ✅", resultado))
.catch(error => console.error("Error ❌", error));
Cada .then() devuelve una nueva promesa, lo que hace posible este flujo secuencial y legible.
🧠 Ejemplo práctico: simulando una API
Veamos un ejemplo completo donde simulamos una petición a un servidor:
function obtenerDatos() {
return new Promise((resolve, reject) => {
console.log("⏳ Solicitando datos...");
setTimeout(() => {
const exito = Math.random() > 0.3; // 70% de éxito
if (exito) {
resolve({mensaje: "Datos recibidos correctamente 📦"});
} else {
reject("Error al obtener datos del servidor 💣");
}
}, 2000);
});
}
obtenerDatos()
.then(res => console.log(res.mensaje))
.catch(err => console.error(err));
🔄 Comparación con async/await
La sintaxis async/await es una forma más moderna y elegante de trabajar con Promesas.
Esencialmente, es azúcar sintáctica que hace que el código luzca más “sincrónico”. 🍬
async function ejecutar() {
try {
const resultado = await obtenerDatos();
console.log(resultado.mensaje);
} catch (error) {
console.error("Error capturado:", error);
}
}
ejecutar();
| Estilo | Ventajas | Cuándo usarlo |
|---|---|---|
.then() y .catch() | Ideal para cadenas de procesos simples o control detallado de cada paso. | Cuando necesites múltiples promesas encadenadas. |
async/await | Más limpio, fácil de leer, similar al código sincrónico. | Cuando quieras un flujo lineal y natural. |
🚫 Errores comunes con Promesas
❌ Olvidar el return
Si no devuelves la promesa dentro de un .then(), el encadenamiento se rompe.
// Incorrecto ❌
then(() => {
procesarDatos(); // no se devuelve nada
})
// Correcto ✅
.then(() => {
return procesarDatos();
})
❌ No manejar errores
Cada promesa debe tener su .catch() o estar dentro de un try/catch si usas async/await.
obtenerDatos()
.then(res => console.log(res))
// Falta catch: si falla, el error se pierde 💥
🧩 Promesas útiles en la práctica
JavaScript incluye varias utilidades integradas para trabajar con múltiples promesas:
| Método | Descripción | Ejemplo |
|---|---|---|
| Promise.all() | Espera a que todas las promesas se resuelvan. | Promise.all([p1, p2]) |
| Promise.allSettled() | Espera a que todas terminen (sin importar si fallan). | Promise.allSettled([p1, p2]) |
| Promise.race() | Devuelve el resultado de la primera que termine. | Promise.race([p1, p2]) |
| Promise.any() | Devuelve la primera que se resuelva correctamente. | Promise.any([p1, p2]) |
Ejemplo con Promise.all()
const promesa1 = new Promise(res => setTimeout(() => res("🍎"), 1000));
const promesa2 = new Promise(res => setTimeout(() => res("🍌"), 2000));
Promise.all([promesa1, promesa2])
.then(frutas => console.log("Frutas listas:", frutas)) // ["🍎", "🍌"]
.catch(console.error);
💡 Buenas prácticas
✅ Siempre maneja errores (.catch() o try/catch).
✅ Evita anidar promesas; usa encadenamiento.
✅ Usa nombres claros para las funciones asíncronas.
✅ Prefiere async/await cuando quieras un flujo más natural.
🎯 Conclusión
Las Promesas transformaron la manera en que JavaScript maneja la asincronía. Comprenderlas es clave para dominar el lenguaje y escribir código más limpio, eficiente y fácil de mantener. 🚀
Prometer no cuesta nada… cumplir, en cambio, requiere práctica. 😉