O problema do promise hell em JavaScript
Você já sabe que as Promises foram criadas para resolver o problema do callback hell. No entanto, com o tempo, descobriu-se que as Promises também podem gerar código complexo. Esse problema, por analogia, foi chamado de promise hell.
Vamos examinar esse problema com exemplos
de código. Suponha que temos uma função getSmth,
que recebe um parâmetro e retorna um resultado
dependendo desse parâmetro:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
Neste caso, estamos simulando uma operação útil (por exemplo, obter dados de um servidor). Para simular, simplesmente passamos um número como parâmetro e após um segundo retornamos o quadrado desse número.
Agora vamos usar nossa função
getSmth dentro de outra função:
function func() {
getSmth(2).then(res => {
console.log(res); // exibirá 4
});
}
func();
Primeiro problema
Múltiplas construções then
seguidas uma após a outra dificultam a compreensão do código:
function func(){
getSmth(2).then(res1 => {
// fazemos algo
}).then(res2 => {
// fazemos algo
}).then(res3 => {
// fazemos algo
}).then(res4 => {
// fazemos algo
}).then(res5 => {
// fazemos algo
}).then(res6 => {
// fazemos algo
});
}
func();
Segundo problema
Há um problema de outra natureza. Suponha que agora queremos usar nossa função duas vezes e depois somar os resultados. Como resultado, teremos um código assim:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // exibirá 13
});
});
}
func();
Já lembra o callback hell, não é? Vamos adicionar mais uma chamada de função - o código ficará ainda pior:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Poderíamos, claro, usar Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
No entanto, obtivemos a mesma coisa? Não! No primeiro caso, cada nova função aguarda a conclusão da Promise anterior, enquanto no segundo caso - todas as Promises são executadas simultaneamente. Essa diferença será significativa no caso em que quisermos passar o resultado da função anterior para a próxima função:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();