Promise hell issue in JavaScript

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();
enru