Проблемата promise hell в JavaScript
Вече знаете, че промисовете бяха създадени, за да решат проблема callback hell. Въпреки това, с времето се оказа, че промисовете също могат да породят сложен код. Този проблем по аналогия беше наречен 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();