Asynchronous JavaScript: Promises Async Await!
Tags: webdev, javascript, beginners, programming
Published: 2023-04-05 21:40:56

## ASYNCHRONOUS JAVASCRIPT
Before we undestand asynchronous javascript code, we need to first understand what synchronous javascript code is (basically the **opposite** of asynchronous code)
### Synchronous Code simply means code that is executed line by line in the exact order of execution
*for example*

```
const p = document.querySelector('.p');
p.textContent = 'My name is Cybermaxi';
alert('Text set');
p.style.color = 'red';
```
The above code will be executed line by line, if anything goes wrong with a line, the remaining lines of code will not run.
For example the alert method which brings out a pop-up window, if we do not click ok, the remaining lines of code will not run. This is the **problem** with synchronous code

Asynchronous code is however executed after a task that runs in the background finishes. The execution does not wait for an asynchronous code to finish before it runs

*For example*

```
const p = document.querySelector('.p');
setTimeout(function(){
    p.textContent = 'My name is Cybermaxi';
}, 5000);
p.style.color = 'red';
```
The setTimeout function is asynchronous in that its callback function will run after timeout is completed. It doesn't block or obstructs other lines of code from executing, **It simply runs on the background**. Whenever the timer finishes (5 seconds), the callback function will run.

**We can therefore say Asynchronous programming is coordinating behavior of a program over a certain period of time**
<u>NB</u> Callback functions alone do not make a code asynchronous, for example the map() that contains a callback isn't asynchronous.

Example of asynchronous behavior in javascript include Geolocation API, AJAX calls etc
This brings us to AJAX.
### WHAT ARE AJAX CALLS
Asynchronous Javascript and XML (AJAX) allows us to communicate with web servers in an asynchronous way. With AJAX, we can request data from web servers dynamically.
####How it works
Let's say we have our web application running in our browser(client), we can request (ask for some data) from a web server a particular data we need, the web server then sends a response back to us which may contain the data we need or an error occurred while trying to get that data.
Note that when requesting, we can  either GET(fetch data) or POST(send data) to the web servers. the web servers usually contains a web API
#### What is a web API?
API stands for Application Programming Interface. It is a piece of software that can be used by another piece of software to allow applications talk to each other.
It can also be seen as an application running on a server, that **receives** request for data and sends data back as **response**.
**NB** There is an API for everything!

In Javascript there are multiple ways of making AJAX calls but let's start with the oldest which is using the XMLHttpRequest();

The **XMLHttpRequest()** object are used to interact with servers, you can retrieve data from a url without having to do a full page reload, this enables a webpage to update a part of the page without disrupting what the user is doing.
Despite it's name, it can be used to retrieve any kind of data not just XML
E.g
`const request = new XMLHttpRequest()`

1. 
The above line of code creates a new XMLHttpRequest object

2. 
The next step is to call the open() method on the request object with the following parameters
`request.open('GET', 'https://url of the api')`
3.
The next step is to call the send() method
`request.send();`
At this point, this is where asynchronous javascript happens. The request is sent and we wait for a response from the API, all this happens behind the scenes, thus not hindering the execution of any line of code that may come afterwards.
4. 
The next step is to attach an event listener on the request object to listen for the load event then do something with the response

```
request.addEventListener('load', function(){
    console.log(this.responseText)
})
```
Wondering where responseText came from? It is a variable name created automatically by he XMLHttpRequest containing the data we requested.
Notice the data you get will be in a string format, we therefore need to convert it into an object
`const data = JSON.parse(this.responseText);`

The second and major way of making request to API is the **Fetch()** 
We simply do

`const request = fetch(url);`
The fetch method returns a **Promise** which brings us to Promises

####WHAT ARE PROMISES


![promises in JavaScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7crs8xa1j97o2sbelfsh.jpg)

- A Promise can be seen as an object that is used as a placeholder for the future result of an asynchronous operation

- A Promise can also be seen as a container for an asynchronously delivered value

- In simple terms a promise is a container for a future value.
An example of such value is a response from AJAX calls

####Two (2) Advantages of Using Promises
1. We no longer have to rely on events and callbacks passed into asynchronous functions to handle asynchronous result
2. Instead of nesting callbacks, we can chain promises for a sequence of asynchronous operation thus escaping callback hell

Since promises work with asynchronous operations, they are time sensitive and as a result they can be in different states, this is called the **Promise Lifecycle**

When a promise is initiated, it is in the **Pending** state, the asynchronous task then gets settled and at this settled state exists two states: the **fulfiled and the rejected** state
- A fulfilled state means successs, the value or response is now available
- A rejected promise means an error has occurred, therefore a failed promise. 

```
fetch('url').then(response => response.json())
.then(data => console.log(data))
```

The fetch API returns a promise which if fulfilled, provides a response, now that response can only be accessed by calling the json() method on it. After calling it, it returns another response which inturns provide us with the data we requested for.

####Building a Promise
We have been using promises but now let us create our own new promise. **A promise is simply a javacript objevt and it is a constructor that accepts only one argument which is called an executor function**. this function takes in two arguments which is the resolve and reject parameters

`const newPromise = new Promise(function(resolve, reject){})`
Use case

```
const lotteryPromise = new Promise(function(resolve, reject){
    console.log('Lottery has began')
    setTimeout(function(){
        if (Math.random() >= 0.5) {
            resolve('You Win');
        } else {
            reject new Error('You Lost')
        }
    }, 2000)
})
```
Now let's consume the promise
`lotteryPromise.then(res => console.log(res)).catch(err => console.error(err))`

However we can consume promises in a more efficient way using the **ASYNC AWAIT** other than the then method chaining


![Async Await in JavaScript](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8oousrtxhofw4ni69gld.png)

In Async Await, we declare the async keyword when defining the function to make that function an async function and then add the await keyword to any asynchronous operations like the fetch() which inturns produces a promise. The **await** simply means wait for the promise to be fulfiled and **one beauty of this is we can be able to store the response in a variable which we couldn't do before**

```
const getNumbers = async function() {
    const res = await fetch(url);
    const data = await res.json();

}
```
Isn't this simple as to when compared with the promise then method chaining?

But what happens when we want to make or carry out multiple promises at the same time not depending on one another we can then 

```
const getThreeNumbers = async function() {
    const data1 = await firstPromise();
    const data2 = await secondPromise();
    const data3 = await thirdPromise();
    const [result] = [data1, data2, data3];
}
```
However the problem with the above code is that each promise must wait for the previous promise to fulfill before it gets executed, but if we want to execute them all at the same time, we can use what is called **Promise.all()** and this returns back a single promise
`const result = Promise.all([
    await firstPromise();
    await secondPromise();
    await thirdPromise();
])`



Despite the length of the post, i hope you found something useful and learnt a thing or two.

Leave a comment on something you learnt and improvements or additions to my post
Thank you 😊