Problém promise hell v JavaScripte
Už viete, že promisy boli vytvorené na to, aby vyriešili problém callback hell. Avšak časom sa ukázalo, že promisy tiež môžu vytvoriť zložitý kód. Tento problém bol analogicky pomenovaný promise hell.
Poďme sa na tento problém pozrieť na príkladoch
kódu. Nech máme funkciu getSmth,
ktorá získava parameter a vracia výsledok
v závislosti od tohto parametra:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
V tomto prípade imitujeme nejakú užitočnú operáciu (napríklad získavanie dát zo servera). Ako simuláciu jednoducho parametrom odovzdáme číslo a po sekunde vrátime štvorec tohto čísla.
Poďme teraz použiť našu funkciu
getSmth vnútri inej funkcie:
function func() {
getSmth(2).then(res => {
console.log(res); // vypíše 4
});
}
func();
Prvý problém
Mnoho nasledujúcich za sebou konštrukcií
then sťažuje pochopenie kódu:
function func(){
getSmth(2).then(res1 => {
// robíme niečo
}).then(res2 => {
// robíme niečo
}).then(res3 => {
// robíme niečo
}).then(res4 => {
// robíme niečo
}).then(res5 => {
// robíme niečo
}).then(res6 => {
// robíme niečo
});
}
func();
Druhý problém
Existuje aj problém iného zamerania. Nech teraz chceme použiť našu funkciu dva krát, potom sčítať výsledky. Výsledkom bude takýto kód:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // vypíše 13
});
});
}
func();
Už pripomína callback hell, nie? Pridajme ešte jedno volanie funkcie - kód sa stane ešte horším:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Samozrejme, môžeme použiť Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Ale dosiahli sme to isté? Nie! V prvom prípade každá nová funkcia čaká na dokončenie predchádzajúceho promisu, zatiaľ čo v druhom prípade - všetky promisy sa vykonávajú súčasne. Tento rozdiel bude podstatný v prípade, keď do ďalšej funkcie budeme chcieť odovzdať výsledok volania predchádzajúcej:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();