¿Qué es Promise?
Promise es un objeto que representa el resultado de una operación asíncrona que se puede obtener ahora, en el futuro o nunca. Es una especie de "promesa" de devolver el resultado cuando la operación se complete.
Promis existe en uno de tres estados:
pending (en espera) — estado inicial, la operación aún se está ejecutando
fulfilled (completado) — la operación se completó con éxito
rejected (rechazado) — la operación finalizó con un error
Es importante entender que una promesa solo puede pasar del estado pendiente una vez, ya sea a cumplido o rechazado. Después de eso, el estado no cambia.
Creación de promesas
La promesa se crea con el constructor Promise, que toma la función ejecutora (executor). Esta función recibe dos argumentos: resolve y reject.
const myPromise = new Promise((resolve, reject) => {
// Operación asíncrona
const success = true;
if (success) {
resolve('The operation was successful!');
} else {
reject('An error occurred');
}
});La función ejecutora se inicia inmediatamente cuando se crea la promesa. Cuando llamas a resolve(value), la promesa pasa al estado fulfilled con el resultado value. Al llamar a reject(error), la promesa se convierte en rejected con error.
Procesamiento de resultados: then, catch, finally
Para trabajar con el resultado de la promesa, se utilizan los métodos then, catch y finally.
myPromise
.then(result => {
console.log('Success:', result);
return result.toUpperCase();
})
.catch(error => {
console.error('Error:', error);
})
.finally(() => {
console.log('Operation completed');
});El método then toma dos argumentos opcionales: una devolución de llamada para una ejecución exitosa y una devolución de llamada para un error. En la práctica, catch se usa con más frecuencia para manejar errores, lo que hace que el código sea más legible.
El método finally siempre se ejecuta, independientemente del resultado de la promesa. Esto es útil para las acciones que deben realizarse en cualquier caso, por ejemplo, ocultar el indicador de carga.
Cadenas de promesas
Una de las principales ventajas de las promesas es la capacidad de crear cadenas de operaciones asíncronas. Cada then devuelve una nueva promesa, lo que permite construir secuencias.
fetch('https://api.example.com/user/1')
.then(response => response.json())
.then(user => {
console.log('Username:', user.name);
return fetch(`https://api.example.com/user/${user.id}/posts`);
})
.then(response => response.json())
.then(posts => {
console.log('User posts:', posts);
})
.catch(error => {
console.error('Error in the chain:', error);
});En la cadena de promesas, un error en cualquier etapa "cae" al catch más cercano. Esto permite procesar los errores de forma centralizada.

Ejemplo práctico: carga de datos
Consideremos un escenario real: la descarga de datos de usuario desde el servidor con el procesamiento de diversas situaciones.
function fetchUserData(userId) {
return new Promise((resolve, reject) => {
// Imitación de la latencia de la red
setTimeout(() => {
const users = {
1: { name: 'Alexey', role: 'developer' },
2: { name: 'Maria', role: 'designer' }
};
const user = users[userId];
if (user) {
resolve(user);
} else {
reject(new Error('User not found'));
}
}, 1000);
});
}
// Uso
fetchUserData(1)
.then(user => {
console.log(`Hi ${user.name}!`);
console.log(`Your role: ${user.role}`);
})
.catch(error => {
console.error('Failed to load data:', error.message);
})
.finally(() => {
console.log('Request completed');
});Promise.all y Promise.race
JavaScript proporciona métodos estáticos útiles para trabajar con múltiples promesas.
Promise.all
El método Promise.all toma una matriz de promesas y devuelve una nueva promesa, que se ejecuta cuando se ejecutan todas las promesas de la matriz. Si se rechaza al menos una promesa, se rechaza todo Promise.all.
const promise1 = Promise.resolve(3);
const promise2 = new Promise(resolve => setTimeout(() => resolve(42), 1000));
const promise3 = fetch('https://api.example.com/data').then(r => r.json());
Promise.all([promise1, promise2, promise3])
.then(results => {
console.log('All results:', results);
// results será una matriz: [3, 42, {...datos de la API}]
})
.catch(error => {
console.error('One of the promisses ended in error:', error);
});Esto es útil cuando se necesita realizar varias operaciones asíncronas independientes y esperar a que todas ellas se completen.
Promise.race
El método Promise.race devuelve una promesa que se ejecuta o se rechaza tan pronto como se ejecuta o se rechaza la primera de las promesas transmitidas.
const slowPromise = new Promise(resolve =>
setTimeout(() => resolve('Slow'), 3000)
);
const fastPromise = new Promise(resolve =>
setTimeout(() => resolve('Fast'), 1000)
);
Promise.race([slowPromise, fastPromise])
.then(result => {
console.log('Winner:', result); // 'Rápido'});Esto es útil para implementar tiempos de espera o seleccionar la fuente de datos más rápida.
Promise.allSettled y Promise.any
Las versiones modernas de JavaScript han añadido dos métodos más útiles.
Promise.allSettled
A diferencia de Promise.all, el método Promise.allSettled espera la finalización de todas las promesas, independientemente del resultado. Devuelve una matriz de objetos con información sobre cada promesa.
const promises = [
Promise.resolve('Success'),
Promise.reject('Error'),
Promise.resolve('More success')
];
Promise.allSettled(promises)
.then(results => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Promis ${index}: executed with value ${result.value}`);
} else {
console.log(`Promo ${index}: rejected with reason ${result.reason}`);
}
});
});Promise.any
El método Promise.any devuelve la primera promesa completada con éxito. Si se rechazan todas las promesas, se devuelve la promesa rechazada con un error agregado.
const promises = [
Promise.reject('Error 1'),
Promise.resolve('Success'),
Promise.reject('Error 2')
];
Promise.any(promises)
.then(result => {
console.log('First successful result:', result); // 'Éxito's'
})
.catch(error => {
console.error('All promissory notes are rejected:', error);
});Errores típicos al trabajar con promesas
Return olvidado en la cadena
Uno de los errores más comunes es olvidar devolver la promesa de then, lo que rompe la cadena.
// Incorrecto
fetchUser()
.then(user => {
fetchPosts(user.id); // ¡Olvidó el return!
})
.then(posts => {
// posts será undefined
console.log(posts);
});
// Correcto
fetchUser()
.then(user => {
return fetchPosts(user.id); // Devolvemos el dinero
})
.then(posts => {
console.log(posts); // Ahora posts contiene datos
});Promesas anidadas en lugar de cadenas
A veces, los desarrolladores crean anidamiento de promesas, lo que nos devuelve al problema del callback-hell.
// Mal: anidamiento
fetchUser()
.then(user => {
fetchPosts(user.id)
.then(posts => {
fetchComments(posts[0].id)
.then(comments => {
console.log(comments);
});
});
});
// Bien: cadena
fetchUser()
.then(user => fetchPosts(user.id))
.then(posts => fetchComments(posts[0].id))
.then(comments => console.log(comments))
.catch(error => console.error(error));Ausencia de gestión de errores
Añade siempre catch para gestionar los errores, de lo contrario pueden pasar desapercibidos.
// Peligroso
fetchData().then(data => console.log(data));
// Seguro
fetchData()
.then(data => console.log(data))
.catch(error => console.error('An error occurred:', error));De las promesas a async/await
Las promesas sentaron las bases de la sintaxis async/await, que hace que el código asíncrono se parezca aún más al código síncrono.
// Con promesas
function getUserInfo() {
return fetchUser()
.then(user => fetchPosts(user.id))
.then(posts => {
return { user, posts };
});
}
// Con async/await
async function getUserInfo() {
const user = await fetchUser();
const posts = await fetchPosts(user.id);
return { user, posts };
}Sin embargo, comprender las promesas es crítico, ya que async/await es azúcar sintáctico sobre las promesas, y conocer su funcionamiento ayuda a usar la asincronía en JavaScript de manera efectiva.
Conclusión
Las promesas han resuelto el problema fundamental de JavaScript: el trabajo elegante con operaciones asíncronas. Proporcionan una interfaz clara para gestionar la secuencia de acciones, el manejo de errores y la composición de operaciones asíncronas.
Puntos clave para recordar:
Promis se encuentra en uno de los tres estados y lo cambia solo una vez
Las cadenas de promesas resuelven el problema de la anidación de las devoluciones
Siempre procesa los errores a través de catch
Utilice Promise.all para ejecutar operaciones independientes en paralelo
Devuelve las promesas de then para construir cadenas correctas
Una comprensión profunda de las promesas es la base para trabajar con JavaScript asíncrono moderno y la transición a async/await.
¿Quieres sistematizar tus conocimientos? En la plataforma Kodik encontrarás cursos prácticos de programación con certificado al final de la formación.
Únete a nuestro nuestro acogedor canal de Telegram — aquí compartimos materiales útiles, discutimos temas interesantes y ayudamos a los desarrolladores novatos a crecer profesionalmente. ¡Juntos aprendemos más!
