Вы уже знаете, что промисы были созданы для того, чтобы решить проблему 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();