El problema de promise hell en JavaScript
Ya sabes que las promesas fueron creadas para resolver el problema del callback hell. Sin embargo, con el tiempo resultó que las promesas también pueden generar código complejo. Este problema por analogía fue llamado promise hell.
Analicemos este problema con ejemplos de
código. Supongamos que tenemos una función getSmth,
que obtiene un parámetro y devuelve un resultado
dependiendo de ese parámetro:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
En este caso estamos simulando una operación útil (por ejemplo, obtener datos de un servidor). Como simulación, simplemente pasamos un número como parámetro y después de un segundo devolvemos el cuadrado de ese número.
Ahora usemos nuestra función
getSmth dentro de otra función:
function func() {
getSmth(2).then(res => {
console.log(res); // mostrará 4
});
}
func();
Primer problema
Múltiples construcciones then
consecutivas dificultan la comprensión del código:
function func(){
getSmth(2).then(res1 => {
// hacemos algo
}).then(res2 => {
// hacemos algo
}).then(res3 => {
// hacemos algo
}).then(res4 => {
// hacemos algo
}).then(res5 => {
// hacemos algo
}).then(res6 => {
// hacemos algo
});
}
func();
Segundo problema
Existe un problema de otro tipo. Supongamos que ahora queremos usar nuestra función dos veces, luego sumar los resultados. Como resultado obtendremos el siguiente código:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // mostrará 13
});
});
}
func();
Ya se parece al callback hell, ¿verdad? Añadamos una llamada más a la función - el código se volverá aún peor:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Por supuesto, se puede usar Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Sin embargo, ¿obtuvimos lo mismo? ¡No! En el primer caso, cada nueva función espera a que se complete la promesa anterior, mientras que en el segundo caso, todas las promesas se ejecutan simultáneamente. Esta diferencia será significativa en el caso en que queramos pasar el resultado de una función anterior a la siguiente:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();