Asynchronous Operations in JavaScript
Tags: javascript, functional, codenewbie, computerscience
Published: 2020-10-12 13:37:01

JavaScript is synchronous by default, which means operations execute from top to bottom. Synchronous operations in JavaScript requires having each step of an operation wait for the previous step to execute completely. This means no matter how long the previous process takes, subsequent process won't start off until the prior is completed.

**Asynchronous means that things can happen independently of the main program flow.**
In Asynchronous operations, any process that takes a lot of time to process is usually run alongside other synchronous operation and completes in the future.
Let us see the fundamental concepts that JavaScript relies on to handle asynchronous operations.

These concepts include:
**Callback functions,
  Promises and
  Async and Await** 
  
For instance:

**console.log("Get up Early");
console.log("Express gratitude for what you have");
console.log("Do something productive and fun");**

If we run the code above, we have the following logged in the console:

**Get up Early
Express gratitude for what you have
Do something productive and fun**

Now let's change that a bit so that 'Express gratitude for what you have' takes longer than 'Do something productive and fun' :

**console.log("Get up Early");**

**setTimeout(function() {**
  **console.log("Express gratitude for what you have")
},3000);**

**console.log("Do something productive and fun");**

We get the following in the console:

**Get up Early
Do something productive and fun
Express gratitude for what you have**

The setTimeout function makes the operation asynchronous by delaying "Express gratitude for what you have" to occur after 3 seconds. The whole operation doesn’t pause for 3 seconds so it can log “Do something productive and fun”.

##__CallBack Functions__
 A callback is a simple function that's passed as a value to another function, and will only be executed when the event happens. We can do this because JavaScript has first-class functions, which can be assigned to variables and passed around to other functions (called higher-order functions).
Using callback functions is a core functional programming concept, and you can find them in most JavaScript code; either in simple functions like **setInterval, event listening or when making API calls**.
The callback function is not run unless called by its containing function. Hence, the term *call back function*.

One common example of callback functions:

**setTimeout(() => {**
*// runs after 2 seconds*
**}, 2000)**

###Problem with callbacks
Callbacks are great for simple cases and are useful for short asynchronous operations. When working with large sets, this is not considered best practice.
Every callback adds a level of nesting, and when you have lots of callbacks, the code starts to become complicated very quickly and sometimes the code becomes incomprehensible and is not easily refactored. This is known as **callback hell**.

###**Alternatives to callbacks**
Starting with ES6, JavaScript introduced several features that help us with asynchronous code that do not involve using callbacks:
1.Promises (ES6)
2.Async/Await (ES8)

##__Promises__
Promises are one way to deal with asynchronous code, without writing too many callbacks in your code.
1.Introduced in ES6.
2.Superseded in 2018, by async functions
**Async Functions** use the promises API as their building block.

###Working of Promises
Promises have 3 states:
**1.Pending State
2.Fulfilled/Resolved State
3.Rejected State**

When the promise has been called, it will start in the Pending State.This means that the caller function continues the execution, while it waits for the promise to do its own processing, and give the caller function some feedback.
The caller function now waits for it to either return the promise in the resolved state or in the rejected state.
If it returns in the resolved state, this means that the specified operation was completed, but if it returns in the rejected state, it means the operation did not complete and an error value is thrown.

###How Promises are Created??
The Promise object is created using the **new** keyword and contains the promise; this is an executor function which has a **resolve** and a **reject** callback. Using resolve and reject helps us to communicate back a value.

For instance:
**const promise = new Promise(function(resolve, reject) {**
 **// promise description**
**})**

###Using Promises

Once a promise has been created, using it is pretty straightforward and simple. We can use them by chaining **.then()** and **.catch()**.

##__Async and Await__
JavaScript is even simpler with the async/await syntax.
Async functions are a combination of promises and generators, and basically, they are a higher level abstraction over promises. Let me repeat: async/await is built on promises.
They reduce the boilerplate around promises, and the "don't break the chain" limitation of chaining promises.
Promises were introduced to solve the famous callback hell problem, but they introduced complexity on their own, and syntax complexity.
Async functions make the code look like it's synchronous, but it's asynchronous and non-blocking behind the scenes.