You already know that promises were created to solve the callback hell problem. However, over time it turned out that promises can also generate complex code. This issue was named the promise hell by analogy.
Let's look at this problem with some code
examples. Suppose we have the getSmth
function that receives a parameter and
returns a result depending on this
parameter:
function getSmth(num) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(num * num), 1000)
});
}
In this case, we are simulating some useful operation (for example, getting data from a server). As a simulation, we simply pass a number as a parameter and after a second return the square of this number.
Let's now use our function getSmth
inside another function:
function func() {
getSmth(2).then(res => {
console.log(res); // shows 4
});
}
func();
First problem
Many then
constructions following
one by another make it difficult to
understand the code:
function func(){
getSmth(2).then(res1 => {
// does something
}).then(res2 => {
// does something
}).then(res3 => {
// does something
}).then(res4 => {
// does something
}).then(res5 => {
// does something
}).then(res6 => {
// does something
});
}
func();
Second problem
There is another problem as well. Now let's say we want to use our function twice, then sum the results. As a result, we will get the following code:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
console.log(res1 + res2); // shows 13
});
});
}
func();
Sounds like a callback hell, doesn't it? Let's add one more function call - the code will become even worse:
function func() {
getSmth(2).then(res1 => {
getSmth(3).then(res2 => {
getSmth(4).then(res3 => {
console.log(res1 + res2 + res3);
});
});
});
}
func();
You can, of course,
use Promise.all
:
function func() {
Promise.all([getSmth(2), getSmth(3), getSmth(4)]).then(res => {
console.log(res[0] + res[1] + res[2]);
});
}
func();
However, did we get the same? Not! In the first case, each new function waits for the completion of the previous promise, and in the second case, all promises are executed at the same time. This difference will be significant when we want to pass a call of the previous function to the next one:
function func() {
getSmth(2).then(res1 => {
getSmth(res1).then(res2 => {
getSmth(res2).then(res3 => {
console.log(res3);
});
});
});
}
func();