Day 21 of 30 of JavaScript
Tags: webdev, javascript, beginners, tutorial
Published: 2024-06-24 18:11:25

Hey reader👋 Hope you are doing well😊
In the last post we have talked about an introduction to Asynchronous and Synchronous JavaScript. In this post we are going to discuss more Asynchronous JavaScript.
So let's get started🔥

## Why we need Asynchronous Programming?

Consider a long running synchronous function (i.e. the next line will get executed only after the previous line has completed executing). Suppose generating prime numbers in range [1,1e10] -:
`
// Function to check if a number is prime
function isPrime(num) {
    if (num <= 1) return false;
    if (num <= 3) return true;

    if (num % 2 === 0 || num % 3 === 0) return false;

    for (let i = 5; i * i <= num; i += 6) {
        if (num % i === 0 || num % (i + 2) === 0) return false;
    }

    return true;
}

// Generate prime numbers in a smaller range for demonstration
let primes = [];
let rangeStart = 1;
let rangeEnd = 1e10; 

for (let i = rangeStart; i <= rangeEnd; i++) {
    if (isPrime(i)) {
        primes.push(i);
    }
}

// Print the primes
console.log("Prime numbers:", primes);

// Print "Hello, World!"
console.log("Hello, World!");
`
Now seeing such a large range this program is going to take large amount of time and resources and the line "Hello World" will be printed after the checking and printing of prime numbers. Suppose we had some important function instead of printing "Hello World" here.This is going to create problem. To resolve this problem we need Asynchronous Programming.

> Asynchronous programming allows our code to run in the background without blocking the execution of other code.

## Example
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bwlqe75p380or6l5uulc.png)
So here you can see that last line is printed before "Inside timeout". This is an example of Asynchronous operation.

## Handling Asynchronous Operations

JavaScript provides several ways to handle asynchronous operations, including **callbacks**, **promises**, and **async/await**.
 
**Callbacks**

Callbacks are the original way to handle asynchronous operations in JavaScript. A callback is a function passed as an argument to another function, to be executed once the asynchronous operation completes.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w0hp6qfi3v837ywulept.png)
So you can see that `fetchData` takes a callback function as an argument that fetches the data and is excuted after the timeout but in this delay the other code runs as it is.
While callbacks are simple to understand, they can lead to "callback hell," where nested callbacks become difficult to read and maintain. We will read more about it in later blogs.

**Promises**

Promises provide a more robust way to handle asynchronous operations, allowing you to chain operations and handle errors more gracefully. A promise represents a value that may be available now, or in the future, or never.
To create a promise, we'll create a new instance of the Promise object by calling the Promise constructor.

The constructor takes a single argument: a function called executor. The "executor" function is called immediately when the promise is created, and it takes two arguments: a resolve function and a reject function.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dcb8516zrxrrmqlxcins.png)
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0c4u07zhn1v99tqyfqg3.png)
A JavaScript Promise object can be:

1. Pending -> initial state, neither fulfilled nor rejected.

2. Fulfilled -> meaning that an operation was completed successfully. 

3. Rejected -> meaning that an operation failed.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/45tnz62y5bm9tmg6owi4.png)
The `fetchData` function returns a new promise, which simulates an asynchronous task using `setTimeout`. Inside the `setTimeout` function, a delay of 2000 milliseconds (2 seconds) is introduced to mimic a time-consuming operation, such as fetching data from a server. After the delay, the promise is resolved with the string "Hello, World!" as the data.
When `fetchData` is called, it initiates the asynchronous operation and returns a promise. The `.then()` method is used to handle the successful resolution of the promise, logging the retrieved data `("Hello, World!")` to the console. Additionally, the `.catch()` method is included to handle any potential errors that might occur during the promise's execution, though in this example, no error is expected. This approach ensures that the main thread remains non-blocked while waiting for the asynchronous task to complete, enhancing the responsiveness of the application.

**Async/Await**

Async/await is built on top of promises and allows us to write asynchronous code that looks synchronous. Async/Await is a feature that allows us to write asynchronous code in a more synchronous, readable way.
**async** is a keyword that is used to declare a function as asynchronous.
**await** is a keyword that is used inside an async function to pause the execution of the function until a promise is resolved.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lbzzajybz8yzcivhyeyu.png)
The `getData` function is declared as an asynchronous function using the async keyword.Inside the asynchronous function, we use the await keyword to wait for the fetch function to complete and retrieve some data from an API.Once the data is retrieved, we use await again to wait and parse the retrieved data as JSON.And then finally, we log the data to the console.
"Aync/Await" is a powerful tool for handling asynchronous operations. It allows for more readable and maintainable code by eliminating the need for callbacks and providing a more intuitive way to handle asynchronous operations.

So this is it for this blog in the next blog we will know more about callbacks. I hope you have understood this blog. Follow me for more.
Thankyou 🩵