En esta página
Promesas
Qué es una promesa?
Una promesa (Promise) es un objeto que representa el resultado futuro de una operación asincrona. Puede estar en uno de tres estados:
- Pending — La operación aun no término
- Fulfilled — La operación se completo con éxito (tiene un valor)
- Rejected — La operación fallo (tiene un error)
Una vez que una promesa se resuelve o rechaza, su estado es inmutable: no puede cambiar.
Crear promesas
El constructor new Promise() recibe una función con dos callbacks:
const promesa = new Promise((resolve, reject) => {
// operación asincrona...
if (éxito) {
resolve(resultado); // transición a fulfilled
} else {
reject(new Error('algo fallo')); // transición a rejected
}
});Consumir promesas
.then()
Recibe el valor cuando la promesa se resuelve. Retorna una nueva promesa, permitiendo encadenar:
promesa
.then(valor => transformar(valor))
.then(transformado => usarlo(transformado));.catch()
Captura cualquier error en la cadena:
promesa
.then(valor => procesarlo(valor))
.catch(error => manejarError(error));.finally()
Se ejecuta siempre, sin importar si la promesa se resolvio o rechazo. Es útil para limpiar recursos (cerrar spinners, liberar locks, etc.).
Encadenar promesas
Cada .then() retorna una nueva promesa. Si retornas un valor, la siguiente promesa se resuelve con ese valor. Si retornas otra promesa, la cadena espera a que se resuelva:
obtenerUsuario(1)
.then(user => obtenerPerfil(user.id))
.then(perfil => obtenerFotos(perfil.albumId))
.then(fotos => mostrarGaleria(fotos))
.catch(error => mostrarError(error));Combinadores de promesas
JavaScript ofrece cuatro métodos estaticos para trabajar con multiples promesas simultaneamente:
| Método | Resuelve cuando... | Rechaza cuando... |
|---|---|---|
Promise.all |
Todas se resuelven | Una falla |
Promise.allSettled |
Todas terminan (éxito o fallo) | Nunca |
Promise.race |
La primera termina | La primera falla |
Promise.any |
La primera tiene éxito | Todas fallan |
Patron: timeout con Promise.race
Un patrón comun es competir una petición contra un timer para implementar timeouts:
function conTimeout(promesa, ms) {
const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
);
return Promise.race([promesa, timeout]);
}Errores comunes
- Olvidar retornar en un
.then()— La siguiente promesa recibeundefined - No manejar errores — Siempre agrega
.catch()al final de la cadena - Crear promesas innecesarias — Si ya tienes una promesa, no la envuelvas en otra
Práctica
- Crea y consume una promesa: Escribe una funcion
esperar(ms)que retorne una promesa que se resuelva despues demsmilisegundos. Consumela con.then()para imprimir un mensaje al resolverse. - Encadena promesas con manejo de errores: Crea dos funciones que retornen promesas:
obtenerUsuario(id)yobtenerPosts(userId). Encadenalas con.then()y agrega.catch()y.finally()para manejar errores y limpieza. - Usa Promise.all y Promise.allSettled: Crea 3 promesas (una que falle intencionalmente) y ejecutalas con
Promise.ally luego conPromise.allSettled. Compara los resultados y observa como cada combinador maneja el fallo.
En la siguiente leccion aprenderemos async/await, la forma moderna de trabajar con promesas.
// Crear una promesa
function buscarUsuario(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) {
resolve({ id, nombre: 'Carlos', email: '[email protected]' });
} else {
reject(new Error('ID invalido'));
}
}, 1000);
});
}
// Consumir con .then/.catch/.finally
buscarUsuario(1)
.then(usuario => {
console.log('Usuario:', usuario.nombre);
return usuario.email;
})
.then(email => {
console.log('Email:', email);
})
.catch(error => {
console.error('Error:', error.message);
})
.finally(() => {
console.log('Busqueda finalizada');
});
// Encadenar promesas (cada .then retorna una nueva promesa)
function obtenerPosts(userId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{ id: 1, título: 'Primer post' },
{ id: 2, título: 'Segundo post' },
]);
}, 500);
});
}
buscarUsuario(1)
.then(usuario => obtenerPosts(usuario.id))
.then(posts => console.log('Posts:', posts))
.catch(error => console.error(error));
// Simular peticiones asincronas con promesas
function obtenerUsuarios() {
return new Promise((resolve) => {
setTimeout(() => resolve([{ id: 1, nombre: 'Ana' }]), 1000);
});
}
function obtenerPosts() {
return new Promise((resolve) => {
setTimeout(() => resolve([{ id: 1, titulo: 'Hola' }]), 1500);
});
}
function obtenerComentarios() {
return new Promise((resolve) => {
setTimeout(() => resolve([{ id: 1, texto: 'Genial!' }]), 800);
});
}
// Promise.all - espera a TODAS (falla si una falla)
Promise.all([obtenerUsuarios(), obtenerPosts(), obtenerComentarios()])
.then(([usuarios, posts, comentarios]) => {
console.log('Todos los datos:', usuarios, posts, comentarios);
})
.catch(error => {
console.error('Una peticion fallo:', error);
});
// Promise.allSettled - espera a todas (nunca falla)
Promise.allSettled([obtenerUsuarios(), obtenerPosts(), obtenerComentarios()])
.then(resultados => {
resultados.forEach(r => {
if (r.status === 'fulfilled') {
console.log('OK:', r.value);
} else {
console.log('Error:', r.reason);
}
});
});
// Promise.race - retorna la primera que se resuelva/rechace
const timeout = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), 5000);
});
Promise.race([obtenerUsuarios(), timeout])
.then(data => console.log('Datos:', data))
.catch(err => console.error(err.message));
// Promise.any - retorna la primera que se RESUELVA
Promise.any([obtenerUsuarios(), obtenerPosts(), obtenerComentarios()])
.then(primera => console.log('Primera exitosa:', primera));
Inicia sesión para guardar tu progreso