Il problema del promise hell in JavaScript
Già sapete che le promise sono state create per risolvere il problema del callback hell. Tuttavia, col tempo si è scoperto che le promise sono anch'esse in grado di generare codice complesso. Questo problema per analogia è stato chiamato promise hell.
Analizziamo questo problema con esempi
di codice. Supponiamo di avere una funzione getSmth,
che riceve un parametro e restituisce un risultato
in base a questo parametro:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
In questo caso stiamo simulando un'operazione utile (ad esempio, il recupero di dati da un server). Come simulazione, passiamo semplicamente un numero come parametro e dopo un secondo restituiamo il quadrato di questo numero.
Utilizziamo ora la nostra funzione
getSmth all'interno di un'altra funzione:
function func() {
getSmth(2).then(res => {
console.log(res); // visualizzerà 4
});
}
func();
Primo problema
Multiple costrutti then
che si susseguono rendono difficile la comprensione del codice:
function func(){
getSmth(2).then(res1 => {
// facciamo qualcosa
}).then(res2 => {
// facciamo qualcosa
}).then(res3 => {
// facciamo qualcosa
}).then(res4 => {
// facciamo qualcosa
}).then(res5 => {
// facciamo qualcosa
}).then(res6 => {
// facciamo qualcosa
});
}
func();
Secondo problema
Esiste un problema anche di altro tipo. Supponiamo ora di voler utilizzare la nostra funzione due volte, per poi sommare i risultati. Come risultato otterremo questo codice:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // visualizzerà 13
});
});
}
func();
Già ricorda il callback hell, vero? Aggiungiamo un'altra chiamata alla funzione - il codice diventerà ancora peggiore:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Si potrebbe, certamente, utilizzare Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Tuttavia, abbiamo ottenuto la stessa cosa? No! Nel primo caso ogni nuova funzione attende il completamento della promise precedente, mentre nel secondo caso - tutte le promise vengono eseguite contemporaneamente. Questa differenza sarà sostanziale nel caso in cui vogliamo passare il risultato di una funzione alla successiva:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();