Problema promise hell în JavaScript
Știți deja că promisiunile au fost create pentru a rezolva problema callback hell. Cu toate acestea, cu timpul s-a dovedit că promisiunile de asemenea pot genera cod complex. Această problemă prin analogie a fost numită promise hell.
Să analizăm această problemă pe exemple
de cod. Să presupunem că avem funcția getSmth,
care primește un parametru și returnează un rezultat
în funcție de acest parametru:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
În acest caz, simulăm o anumită operație utilă (de exemplu, obținerea de date de la server). Ca simulare, pur și simplu transmitem ca parametru un număr și după o secundă returnăm pătratul acestui număr.
Acum să folosim funcția noastră
getSmth în interiorul altei funcții:
function func() {
getSmth(2).then(res => {
console.log(res); // va afișa 4
});
}
func();
Prima problemă
Multe construcții then
care se succed una după alta îngreunează înțelegerea codului:
function func(){
getSmth(2).then(res1 => {
// facem ceva
}).then(res2 => {
// facem ceva
}).then(res3 => {
// facem ceva
}).then(res4 => {
// facem ceva
}).then(res5 => {
// facem ceva
}).then(res6 => {
// facem ceva
});
}
func();
A doua problemă
Există o problemă și de altă natură. Să presupunem acum că vrem să folosim funcția noastră de două ori, apoi să însumăm rezultatele. În rezultat vom obține un cod ca acesta:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // va afișa 13
});
});
}
func();
Deja amintește de callback hell, nu-i așa? Să mai adăugăm un apel de funcție - codul va deveni și mai rău:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Putem, desigur, să folosim Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Dar am obținut același lucru? Nu! În primul caz fiecare nouă funcție așteaptă finalizarea promisiunii anterioare, iar în al doilea caz - toate promisiunile se execută simultan. Această diferență va fi substanțială în cazul în care în următoarea funcție vom dori să transmitem rezultatul apelului anterior:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();