Promise'i põrgu probleem JavaScriptis
Te juba teate, et promisid loodi selleks, et lahendada callback hell'i probleemi. Siiski, aja jooksul selgus, et promisid suudavad samuti tekitada keerulist koodi. Seda probleemi nimetati analoogia põhjal promise hell'iks.
Vaatleme seda probleemi koodinäidete abil.
Oletame, et meil on funktsioon getSmth,
mis saab parameetri ja tagastab tulemuse
sõltuvalt sellest parameetrist:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
Antud juhul me imiteerime mingit kasulikku operatsiooni (näiteks andmete saamist serverist). Imitatsioonina me lihtsalt edastame parameetrina numbri ja sekundi pärast tagastame selle numbri ruudu.
Kasutame nüüd meie funktsiooni
getSmth teise funktsiooni sees:
function func() {
getSmth(2).then(res => {
console.log(res); // väljastab 4
});
}
func();
Esimene probleem
Paljud üksteisele järgnevad konstruktsioonid
then raskendavad koodi mõistmist:
function func(){
getSmth(2).then(res1 => {
// teeme midagi
}).then(res2 => {
// teeme midagi
}).then(res3 => {
// teeme midagi
}).then(res4 => {
// teeme midagi
}).then(res5 => {
// teeme midagi
}).then(res6 => {
// teeme midagi
});
}
func();
Teine probleem
On olemas ka teist tüüpi probleem. Oletame nüüd, et me tahame kasutada meie funktsiooni kaks korda, seejärel liita tulemused kokku. Tulemusena saame me sellise koodi:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // väljastab 13
});
});
}
func();
Juba meenutab callback hell'i, kas pole? Lisame veel ühe funktsiooni väljakutse - kood muutub veel hullemaks:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Võib muidugi kasutada Promise.all'i:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Kuid kas me saime sama tulemuse? Ei! Esimesel juhul ootab iga uus funktsioon eelmise promise'i lõppemist, teisel juhul aga - kõik promisid täidetakse samaaegselt. See erinevus on oluline juhul, kui me tahame järgmisesse funktsiooni edastada eelmise väljakutse:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();