Node.js Promise
Promise es uno de los conceptos centrales para manejar operaciones asíncronas en Node.js.
Promise proporciona una forma más elegante de gestionar código asíncrono, evitando el problema clásico del "Callback Hell" (infierno de callbacks).
Este artículo detalla el concepto, el uso y los patrones comunes de Promise.
¿Qué es Promise?
Promise es un objeto que representa la finalización o el fallo eventual de una operación asíncrona. Tiene tres estados:
- Pending (pendiente): estado inicial, ni exitoso ni fallido
- Fulfilled (cumplido): la operación se completó con éxito
- Rejected (rechazado): la operación falló

Una vez que el estado de un Promise cambia (de pending a fulfilled o rejected), no vuelve a cambiar.
Crear un Promise
En Node.js, se puede utilizar elPromiseconstructor para crear un nuevo objeto Promise:
Ejemplo
// operación asíncrona
const success = true; // supongamos que este es el resultado de la operación asíncrona
if (success) {
resolve('¡operación exitosa!'); // el estado cambia a fulfilled
} else {
reject('¡operación fallida!'); // el estado cambia a rejected
}
});
Usando Promise
Promise proporciona los.then()y.catch()métodos para manejar casos de éxito y de fallo:
Ejemplo
.then((result) => {
console.log(result); // salida: "¡operación exitosa!"
})
.catch((error) => {
console.error(error); // salida: "¡operación fallida!"
});
Cadena de promesas (Promise chaining)
El poder de Promise radica en poder encadenar múltiples operaciones asíncronas:
Ejemplo
return new Promise((resolve) => {
setTimeout(() => resolve('primer paso completado'), 1000);
});
}
function asyncOperation2(data) {
return new Promise((resolve) => {
setTimeout(() => resolve(`${data},segundo paso completado`), 1000);
});
}
asyncOperation1()
.then((result) => asyncOperation2(result))
.then((finalResult) => {
console.log(finalResult); // salida: "primer paso completado, segundo paso completado"
})
.catch((error) => {
console.error('Error en la cadena:', error);
});
Métodos estáticos de Promise
Promise ofrece algunos métodos estáticos útiles:
Promise.all()
Espera a que todos los Promise se completen, o a que cualquier Promise falle:
Ejemplo
const promise2 = Promise.resolve('segundo');
Promise.all([promise1, promise2])
.then((results) => {
console.log(results); // salida: ['primero', 'segundo']
});
Promise.race()
Devuelve el Promise que se complete o falle primero:
Ejemplo
const promise2 = new Promise((resolve) => setTimeout(resolve, 100, 'segundo'));
Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // salida: "segundo"
});
Manejo de errores
El manejo de errores de Promise se puede implementar mediante.catch()o.then()el segundo parámetro:
Ejemplo
.then(
(result) => { /* manejar éxito */ },
(error) => { /* manejar fallo */ }
);
// o
someAsyncFunction()
.then((result) => { /* manejar éxito */ })
.catch((error) => { /* manejar todos los errores */ });
Sintaxis async/await
ES2017 introdujo la sintaxis async/await, haciendo el uso de Promise más intuitivo:
Ejemplo
try {
const result1 = await asyncOperation1();
const result2 = await asyncOperation2(result1);
console.log(result2);
} catch (error) {
console.error(error);
}
}
runOperations();
Mejores prácticas
- Siempre maneja los errores: no ignores
.catch()o try-catch - Evita el anidamiento: usa encadenamiento o async/await para mantener el código plano
- Nombra los Promise: asigna nombres significativos a las variables Promise
- Retorna Promise: retorna Promise en las funciones para permitir el encadenamiento