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