Javascript Callback functions & Promises
Tags: javascript, callbacks, promises, callbackhell
Published: 2022-08-15 16:20:00

Callback functions are known to many programming languages, with almost similar style and purpose.

## What are Callback functions
In simple terms, a function passed as an argument to another function is a Callback function.

## Why do we need them ?
You must be wondering, what's so special about these Callback functions, couldn't we already call one function from inside the other.

To get our answers, let's look at these 2 types of network calls.
- Sync
- Async

---

### Sync Vs Async Calls

![sync vs async calls](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/23qdpc84g6xwlfarath3.png)


Callback functions are particularly used for handling the Async responses.

---
{% embed https://youtu.be/4kBX73mRNpI %}
---
## Callback Hell


> _Anything that can go wrong will go wrong_. - Murphy's I Law


A Callback hell is a situation you might intentionally or unintentionally create to make things works, which can have few consequences.

Consider having a tree of nested `setTimeout()` function, In the world of programming Nesting is infamous and notorious.
Why - Well, they make code unreadable, complex, vulnerable to breaking. 

![callback Hell](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ef3pi6nx4bvjgduqsf0z.png)

---

## Promises
Promises in JavaScript are similar to their literal meaning. It's an object through which you can associate handlers for async operations, way ahead in time, similar to a callback functions just that Promises are more clean and easy to manage.
and yes, you can avoid Callback hell with Promises.

Promises can be one of these states 
1. pending - initial/default state
2. fulfilled - promise is resolved, using `resolve()`
3. rejected - promise is rejected, using `reject()`

![Promises states](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xz77s4rpcjeabvvwubdo.png)

Now, let's create a simple promise

```
const promise = new Promise((resolve, reject) => {
	if(res) {
		resolve('resolved')
	} else {
		reject('reject')
	}
})

promise.then(function(){
// On Successful response
// do whatever you feel like

})
```
In this example, we are creating a promise object by instantiating it with a `constructor`. 
The constructor takes in a callback function which has handlers for `resolved` and `rejected` promises.

What happens after a Promise is resolved or rejected is decided by `then()`.

---
{% embed https://youtu.be/8lk5OxGoxSw %}
---
## Promise Chains

When you are working with API calls, after receiving a response you would generally want to perform another call.
so we need to create **promise chains,** by appending one `then()` after the other.

Do remember that all the resolved promises will be handled by `resolve handlers` and rejected promises will be handled by `reject handlers`.

checkout this code,

```
function promise() {
    const jobPromise = new Promise((resolve, reject) => {
        let selected = true; 

        setTimeout(() => {
            if (selected) {
                resolve('Passed Interview');
            } else {
                reject('Failed Interview');
            }
        }, 1000);

    })

    return jobPromise
}

promise()
    .then(decision, jobSearch)
    .then(joining, negotiate)

function decision(param){
    console.log(param)
    let accept = true;
    return new Promise ((resolve, reject) => {
        if (accept) {
            resolve('accept offer')
        } else {
            reject('reject offer')
        } 
        
    });

}

function jobSearch (outcome) {
    console.log(outcome)
    console.log('Back to Job Search')
    return new Promise((resolve, reject) => { reject() })
}

function negotiate () {
    console.log('negotiation starts..... ')
}
function joining (decision) {
    console.log('Revert to the Company', decision);
    console.log('Joining Company')
}
```

## What could go wrong 
If promises are handled injudiciously, an error could easily pass by unnoticed.
Make sure to return a promise in your callback handlers within then() or throw an Error, otherwise the next resolve handler in chain will be invoked and we don’t want that.