Problem promise hell v JavaScriptu
Že veste, da so bili promisi ustvarjeni za rešitev problema callback hell. Vendar se je sčasoma izkazalo, da lahko tudi promisi povzročijo zapleteno kodo. Ta problem je bil po analogiji imenovan promise hell.
Oglejmo si ta problem na primerih
kode. Recimo, da imamo funkcijo getSmth,
ki prejme parameter in vrne rezultat
odvisno od tega parametra:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
V tem primeru posnemamo neko uporabno operacijo (na primer, pridobivanje podatkov s strežnika). Kot simulacijo preprosto parameter podamo število in čez sekundo vrnemo kvadrat tega števila.
Zdaj pa uporabimo našo funkcijo
getSmth znotraj druge funkcije:
function func() {
getSmth(2).then(res => {
console.log(res); // izpiše 4
});
}
func();
Prva težava
Številne konstrukcije then,
ki sledijo ena za drugo, otežujejo razumevanje kode:
function func(){
getSmth(2).then(res1 => {
// naredimo nekaj
}).then(res2 => {
// naredimo nekaj
}).then(res3 => {
// naredimo nekaj
}).then(res4 => {
// naredimo nekaj
}).then(res5 => {
// naredimo nekaj
}).then(res6 => {
// naredimo nekaj
});
}
func();
Druga težava
Obstaja pa tudi težava drugačne narave. Recimo, da zdaj želimo uporabiti našo funkcijo dvakrat, nato pa seštejemo rezultate. Kot rezultat bomo dobili takšno kodo:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // izpiše 13
});
});
}
func();
Že spominja na callback hell, kajne? Dodajmo še en klic funkcije - koda bo postala še slabša:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Seveda lahko uporabimo Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Toda, ali smo dobili isto? Ne! V prvem primeru vsaka nova funkcija čaka na zaključek prejšnjega promisa, v drugem primeru pa se vsi promisi izvajajo sočasno. Ta razlika bo pomembna v primeru, ko bomo želeli v naslednjo funkcijo posredovati klic prejšnje:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();