How to Escape Callback Hell with JavaScipt Promises
Tags: javascript, beginners
Published: 2019-10-21 05:18:10

What's callback hell and what the hell are Promises??  To dive into those questions requires some basic understanding of the Javascript callstack, so I'll go into brief detail about that first and then navigate you through and out of callback hell. 


###**Nature of the Beast**###
JavaScript is a single threaded language - meaning it has a single callstack and it can only **execute one line of code at a time.**. 

The **callstack** is basically a data structure which keeps track of what the program should run next. It follows the rules of FIFO - First In, First Out. 

Step into a function call and it gets adds to the top of the stack, return a function and it pops off the top of the stack.  

You wouldn't grab the waffle at the bottom of the stack. Neither would JavaScript. 

![](https://thepracticaldev.s3.amazonaws.com/i/4rcsce8me8zwyzgtfkaa.png)

So yeah, Javascipt has a single callstack. And this actually makes writing code simple because you don’t have to worry about the concurrency issues - or multiple computations happening at the same time. 

 Great! 

...except when you **do** want stuff to happen at the same time. For example,  writing web applications that make dozens of asynchronous calls to the network - you dont want to stop the the rest of your code from executing just to wait for a response. When this happens, its called holding up the event loop or "main thread". 


###**Callback Hell**###

The first solution to work around JavaScript's single thread is **to nest functions as callbacks.**

It gets the job done, but determining the current scope and available variables can be incredibly challenging and frustrating.

And it just makes you feel like:  

![](https://thepracticaldev.s3.amazonaws.com/i/0jcwqsd78si29lue3xcq.gif)

When you have so many nested functions you find yourself getting lost in the mist - this is whats referred to as **callback hell**. Its scary and no one wants to be there!  

Nested callbacks tends to develop a distinct pyramid shape -
```javascript
fightTheDemogorgon(function(result) {
  rollForDamage(result, function(seasonsLeft) {
    closeTheGate(seasonsLeft, function(finalResult) {
      console.log('Hawkins is safe for ' + finalResult + ' more seasons.');
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
```

**And just imagine this happening even further, with 10 or 15 more nested functions calls. SCARY RIGHT??**

JavaScript developers recognized this was a problem, and they created **Promises.**

Introduced in ES6 (2015), a Promise is an alternative way to format your asynchronous functions without breaking the event loop.  It returns a special promise object that represents a future result. 

###**Whats the Difference?**###

A lot of it is formatting. 

Callbacks do  not return anything right away, they take a function as an argument, and then you tell the executing function what to do when the asynchronous task completes.

Promises on the other hand immediately return a special promise object. They do not need a function argument, thus it does not need to be nested. 
You provide the action to be taken when the asynchronous task completes using a promise method called **then()**. 


###**Chaining, aka the Power of Friendship**###
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/32pbix2d0cl6pqur5i6z.jpg)

The truly **AWESOME** thing about Promises is that they can be **chained** by using their **then()** method when we need to execute two or more asynchronous operations back to back. 

Each chained then() function returns a new promise, different from the original and represents the completion of another asynchronous step in the chain.

You can basically read it as **Do this, THEN do this, THEN this.**

Promises also have a catch() method. Chaining a catch() to end of a chain will give you the errors for **any failed promise in the chain**. Its also useful to set an action to take in the event of a failure in the chain.

Promise chaining allows us to get rid of the nasty nesting callback pattern and flatten our JavaScript code into more readable format.

```javascript
fightTheDemogorgon()
.then(function(result) {
  return rollForDamage(result);
})
.then(function(seasonsLeft) {
  return closeTheGateIn(seasonsLeft);
})
.then(function(finalResult) {
  console.log('Hawkins is safe for ' + finalResult + ' more seasons.');
})
.catch(failureCallback);
```
With ES6 syntax we can condense this even further! 


```javascript
fightTheDemogorgon()
.then((result) => rollForDamage(result))
.then((seasonsLeft) => closeTheGateIn(seasonsLeft))
.then((finalResult) => console.log('Hawkins is safe for ' + finalResult + ' more seasons.'))
.catch(failureCallback);
```

###**Defeating the Beast, Escaping Hell**###

The beast here being asynchronous calls, and hell being callback hell.

There is nothing stopping you from nesting Promise functions in typical callback fashion. **But it's not necessary!** This is usually accidentally self inflicted and is just a lack a familiarity with Promises.

You can think of Promises as callbacks in fancy new clothes.  It allows asynchronous code to look cleaner, promotes ease of use and readability, most importantly, it gives you a way out of callback hell. 


![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/fenib8mt3142d7ttvtds.gif)


There is an even **newer** method called Async/await introduced in ES8 (2017). Check it out! 

###Thanks for reading!###


References: 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
https://www.youtube.com/watch?v=8aGhZQkoFbQ