Праblema promise hell у JavaScript
Вы ўжо ведаеце, што промісы былі створаны для таго, каб вырашыць праблему callback hell. Аднак, з часам апынулася, што промісы таксама здольныя параждаць складаны код. Гэтая праblema па аналогіі была названа promise hell.
Давайце расгледзім гэтую праблему на прыкладах
кода. Хай у нас ёсць функцыя getSmth,
якая атрымлівае параметр і вяртае вынік
у залежнасці ад гэтага параметра:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
У гэтым выпадку мы імітуем некаторую карысную аперацыю (напрыклад, атрыманне дадзеных з сервера). У якасці імітацыі мы проста параметрам перадаем лік і праз секунду вяртаем квадрат гэтага ліку.
Давайце цяпер скарыстаемся нашай функцыяй
getSmth унутры іншай функцыі:
function func() {
getSmth(2).then(res => {
console.log(res); // выведзе 4
});
}
func();
Першая праблема
Мноства наступных адзін за адным канструкцый
then ускладняюць разуменне кода:
function func(){
getSmth(2).then(res1 => {
// робім што-небудзь
}).then(res2 => {
// робім што-небудзь
}).then(res3 => {
// робім што-небудзь
}).then(res4 => {
// робім што-небудзь
}).then(res5 => {
// робім што-небудзь
}).then(res6 => {
// робім што-небудзь
});
}
func();
Другая праблема
Ёсць праблема і іншага плана. Хай цяпер мы хочам скарыстацца нашай функцыяй два разы, затым прасумаваць вынікі. У выніку ў нас атрымаецца вось такі код:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // выведзе 13
});
});
}
func();
Ужо нагадвае callback hell, ці не так? Дадамо яшчэ адзін вызаў функцыі - код стане яшчэ горшым:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
Можна, вядома ж, скарыстацца Promise.all:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
Аднак, ці атрымалі мы тое ж самае? Не! У першым выпадку кожная новая функцыя чакае завяршэння папярэдняга проміса, а ў другім выпадку - усе промісы выконваюцца адначасова. Гэтая розніца будзе істотная ў тым выпадку, калі мы ў наступную функцыю захочам перадаць вызаў папярэдняй:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();