A promise hell problémája a JavaScriptben
Már tudod, hogy a promise-okat azért hozták létre, hogy megoldják a callback hell problémáját. Azonban idővel kiderült, hogy a promise-ok is képesek bonyolult kódot szülni. Ezt a problémát analógia alapján promise hell-nek nevezték el.
Nézzük meg ezt a problémát kódpéldákon keresztül.
Legyen egy getSmth függvényünk, amely
kap egy paramétert és visszaad egy eredményt
ennek a paraméternek a függvényében:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
Ebben az esetben egy hasznos műveletet szimulálunk (például adatok lekérését a szerverről). A szimuláció érdekében egyszerűen egy számot adunk át paraméterként, és egy másodperc múlva visszaadjuk a szám négyzetét.
Most pedig használjuk a getSmth függvényünket
egy másik függvényen belül:
function func() {
getSmth(2).then(res => {
console.log(res); // kiírja a 4-et
});
}
func();
Első probléma
Az egymást követő then szerkezetek sokasága
megnehezíti a kód megértését:
function func(){
getSmth(2).then(res1 => {
// csinálunk valamit
}).then(res2 => {
// csinálunk valamit
}).then(res3 => {
// csinálunk valamit
}).then(res4 => {
// csinálunk valamit
}).then(res5 => {
// csinálunk valamit
}).then(res6 => {
// csinálunk valamit
});
}
func();
Második probléma
Van egy másik jellegű probléma is. Tegyük fel, hogy most kétszer szeretnénk használni a függvényünket, majd összegezni az eredményeket. Ennek eredményeképpen ilyen kódot kapunk:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // kiírja a 13-at
});
});
}
func();
Már emlékeztet a callback hell-re, nem igaz? Adjunk hozzá még egy függvényhívást - a kód még rosszabb lesz:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Természetesen használhatnánk a Promise.all-t:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
De vajon ugyanazt kaptuk-e? Nem! Az első esetben minden új függvény megvárja az előző promise befejeződését, míg a második esetben - minden promise egyszerre fut le. Ez a különbség akkor lesz jelentős, amikor az előző hívás eredményét szeretnénk átadni a következő függvénynek:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();