What is Asynchronous JavaScript?
Tags: javascript, programming, webdev
Published: 2023-07-14 09:16:57

​​Asynchronous simply refers to making many events occur simultaneously in any order without waiting for one another, and this definition applies to asynchronous Javascript.
​​
​​In this article, I'll go through the concept of asynchronous JavaScript, Callback, Promises, Async/Await, Callback queue, Event Loop, and Web browser features (Web API).
​​
​​Javascript is a single-threaded language that can only run one process at a time. JavaScript uses an event loop to carry out the operation, for now, consider the event loop as a queue where all Javascript processes are maintained and executed one at a time.

> You should note Javascript is actually a Synchronous language. JavaScript executes lines of code sequentially, not concurrently, because it is by default, synchronous and single-threaded. 

​​For instance, the code below will run and be executed line by line.
```js
​​let username = "John";
​​let points = 5000;
​​let message = `${username} has earned ${points} points`;
​​
​​console.log(message);
​​
​​//Output
​​John has earned 5000 points
```
The code above is executed synchronously, each line is completed before moving on to the next line.
​​
​​Let's consider a scenario where you need to retrieve a large amount of data from an API and display it. By default, in JavaScript, the execution is blocked, and all further instructions are halted until the retrieval request is completed. This is where asynchronous programming becomes crucial.

<img width="100%" style="width:100%" src="https://media.giphy.com/media/xT9IgLBsyBazb3SKmk/giphy.gif">

​​Let’s dive in. 

## ​​What is Asynchronous JavaScript

​​Asynchronous JavaScript refers to the programming paradigm in which code execution does not follow the usual sequential flow from top to bottom. Instead, asynchronous code allows certain operations to be initiated and completed separately without blocking the execution of other code.
​​
​​The concept of asynchronous JavaScript enables you to break down big complex projects into smaller tasks.

# What is involved in Asynchronous JavaScript?

- Web Browser features (Web API).
- Callback queue.
- Event loop.
- Callback.
- Async/Await.
- Promise.

## Web Browser Features (Web API)
Browser APIs, also known as web APIs, are pre-existing interfaces embedded within web browsers. These APIs offer built-in functionalities that can be leveraged within web applications. 

Web APIs allow developers to access and interact with these additional functionalities using JavaScript. By utilizing web APIs, developers can seamlessly incorporate specific features into their codebase while minimizing code complexity. Examples of such features include making network requests and efficiently managing client-side storage.

Some web browser features include:

- `setTimeout()`

> The `setTimeout()` method allows you to run a block of code after a certain time delay. It is designed to execute the code once. 

The syntax of `setTimeout()` is:
```js
setTimeout(function, milliseconds);
```
Example:
```js
function username() {
  console.log("John")
}

setTimeout(username, 5000)
console.log("Doe")
```
Output:
```
Doe
John
```

- `setInterval()`

> The `setInterval()` method repeats a block of code at every given timing event.

The syntax of `setInterval()`  is :
```js
setInterval(function, milliseconds);
```
Example:
```js
// program to display a text using setInterval method
function orderItem() {
    console.log('I want a bag');
}

setInterval(orderItem, 1000);
```
Output:
```
I want a bag
I want a bag
I want a bag
I want a bag
...
```
In the above  program, the `orderItem()` function is invoked by the `setInterval()` method at an interval of 1000 milliseconds. Consequently, the program outputs the message "I want a bag" every 1 second.

- `clearTimeout()`

> `clearTimeout()` method cancels a timeout previously established by calling `setTimeout()`.

The syntax of `clearTimeout()` is:

```js
clearTimeout(timeoutId)
```

Example:
```js
// Set a timeout that logs a message after 3 seconds
const timeoutId = setTimeout(() => {
  console.log("Timeout executed!");
}, 3000);

// Clear the timeout before it executes
clearTimeout(timeoutId);
```
Output:
If you run the code snippet provided, there will be no output. The `clearTimeout()` function cancels the execution of the timeout set by `setTimeout()` preventing the callback function from being invoked. As a result, the message “Timeout executed!" will not be logged to the console.

- `clearInterval()`

 > `clearInterval()` is used If you want to stop the function call.

The syntax of `clearInterval()` is:
```js
clearInterval(intervalId);
```
Example:
```js
// Define a variable to store the interval ID
let intervalId;

// Function to be executed repeatedly
function showMessage() {
  console.log("Hello!");
}

// Start the interval
intervalId = setInterval(showMessage, 1000);

// After 5 seconds, stop the interval
setTimeout(() => {
  clearInterval(intervalId);
  console.log("Interval stopped");
}, 5000);
```

Output:
```
Hello!
Hello!
Hello!
Hello!
Interval stopped
```
In the above program, you first declare a variable `intervalId` to store the ID returned by `setInterval` function. The `showMessage` function is defined, which will be executed repeatedly every 1000 milliseconds (1 second) using `setInterval`.
After 5 seconds (5000 milliseconds), `clearInterval` is called with the `intervalId` as the argument to stop the interval. This will stop the execution of the `showMessage` function. Finally, a message is logged to the console indicating that the interval has been stopped.

- `fetch()`

> The fetch() method in JavaScript is used to request data from a server.

They are not part of the JavaScript language, but they are built on top of the core JavaScript language, providing you with extra superpowers to use in your JavaScript code. 

 Read more about Web APIs 👉 [here](https://developer.mozilla.org/en-US/docs/Web/API) 👈.

## Callback queue

The callback queue is where the callback function is pushed and awaits execution. The callback queue follows the First-In-First-Out(FIFO) principle.

Now let’s go through this example:

```js
function username() {
  console.log("John")
}

setTimeout(username, 5000)
console.log("Doe")
```
```
//output
Doe
John
```
This block of code demonstrates the usage of the `setTimeout()` function to delay the execution of a callback function.

Here's how it works:

- The `username` function is defined and stored in the Global memory, which logs the string "John" to the console.

- The `setTimeout()` function is called with two arguments. The first argument is the `username` function, which specifies the callback function to be executed, and the second argument is the delay in milliseconds, which in this case is 5000 milliseconds (or 5 seconds).

- After calling `setTimeout()`, the code continues to the next line and logs the string "Doe" to the console.

- The string "Doe" is logged to the console first.

- After the delay of 5000 milliseconds, the `username` function is executed and logs the string "John" to the console. 


## Event Loop
The event loop continuously checks if the call stack is empty. If the call stack is empty, it means that there are no functions currently being executed. In that case, the loop takes the functions waiting in the callback queue and pushes them onto the call stack for execution. The event loop acts like a gatekeeper for the callback queue. 

The event loop manages code execution to avoid blocking, enabling the program to proceed with its operation even during the completion of asynchronous tasks. 

## What is Callback?

When you pass a function as an argument to another function, and that function is invoked or executed within the outer function, it is commonly referred to as a callback function.


![Callback Illustration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/orf7rlcyy9mo7wyzz2cy.png)

Now let’s go through this example:

```js
function placeOrder() {
    setTimeout(() => {
       return (Math.random() * 10) <= 5 ? 'Bag' : 'Shoe';
    }, 2000);
}

let order = placeOrder();
console.log('Order is for: ' + order);

//Output
// Order is for: undefined
```

Here in the `placeOrder` function, the `setTimeout()` will run after 2 seconds, and by that time the `console.log` statement has already been executed, the printed value of `order` is undefined.

Now, you can resolve this issue by logging your message to the console only after the data has returned from `placeOrder`. This can be done by passing a callback function to `placeOrder`, which will be invoked inside the `placeOrder` function.

```javascript
function placeOrder(callback) {
    setTimeout(() => {
        const order = (Math.random() * 10) <= 5 ? 'Bag' : 'Shoe';
        callback(order);
    }, 2000);
}

placeOrder((order) => {
    console.log('Order is for: ' + order);
});

//Output
// Order is for: Bag
```
After two seconds, the callback function will be called, and the console statement will get executed with the correct order value.

> The output of placeOrder function may differ in your case as you are using `Math.random()` to decide order value.

## Promise

[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) is an object in JavaScript that represents the eventual completion (or failure) of an asynchronous operation and its resulting value.

Promises simplify handling asynchronous code, making it easier to write and maintain asynchronous operations without resorting to callback functions or nested callbacks (known as callback hell). 

> Callback hell is a term used to describe a situation where the code becomes hard to read and understand due to a large number of nested callback functions.

A promise can be in one of three states:

- Pending: The initial state when a promise is created, and the asynchronous operation is still ongoing.
- Fulfilled: The state when the asynchronous operation is successfully completed, and the promise has a resolved value.
- Rejected: The state when the asynchronous operation encounters an error or fails, and the promise has a reason for rejection.

There are three main aspects of promises.

- Creating a promise
- Handling a promise
- Chaining of promise


### Creating Promises

To create a promise, you use the Promise constructor, which accepts a function (commonly referred to as the executor) as an argument. The executor function is provided with two parameters: resolve and reject. Within the executor function, you execute your asynchronous task and invoke either resolve or reject based on the result.

Here's an example of creating a promise :

```js
const fetchData = new Promise((resolve, reject) => {
  // Simulating asynchronous task (e.g., making an API call)
  setTimeout(() => {
    const data = { id: 1, name: "John Doe" };
   // Fulfilled the promise with the fetched data
    resolve(data); 
    reject(new Error("Failed to fetch data")); 
    // Alternatively, reject the promise with an error
  }, 2000);
});
```

### Handling a Promise

After creating a promise, you can assign callbacks to handle the result using the `then()` and `catch()` methods.

The `then()` method takes a callback function as an argument and manages the fulfilled promise. It receives the resolved value or result of the promise as an argument.

The `catch()` method is used to handle the rejection of a promise and it is called when the promise is rejected, allowing you to handle any errors that occurred during the asynchronous operation.

Now let's go through this example:

```js
fetchData
  .then((data) => {
    // Handle the fulfilled promise (access the resolved value)
    console.log("Fetched data:", data);
  })
  .catch((error) => {
    // Handle the rejected promise (access the error)
    console.log("Error:", error);
  });
```

### Chaining Promises

Using the `then()` method, you can chain promises together to create a sequence of asynchronous operations. Each `then()` callback produces a new promise, enabling you to handle the outcome of the previous operation and proceed with the next one. Chaining promises allows you to establish a more sequential and readable flow of asynchronous operations.

```js
fetchData
  .then((data) => {
    // Handle the first fulfilled promise
    console.log("Fetched data:", data);
    return someOtherAsyncTask(); 
 // Return a new promise
  })
  .then((result) => {
    // Handle the result of the second fulfilled promise
    console.log("Second async task result:", result);
  })
  .catch((error) => {
    // Handle any errors in the chain
    console.log("Error:", error);
  });
```

## Async/Await

Async/Await is a relatively recent addition to JavaScript, introduced in ES8, that provides a means to write asynchronous code in a synchronous manner.

If you use the `Async` keyword before the function definition, you can then use await within the function. `Await` gives you the power to pause the function in a non-blocking way until the promise is resolved.

Now let's go through this example:

```javascript
async function fetchData() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/posts');
    const data = await response.json();
    console.log('Fetched data:', data);
  } catch (error) {
    console.log('Error fetching data:', error);
  }
}
fetchData();
```

Here’s the explanation to the code snippet:
- An async function called `fetchUserData()` is declared. Inside this function, an asynchronous HTTP request is made to the API endpoint using the `fetch()` function. The `fetch()` function returns a promise that resolves to a response object.
- The execution is paused using the `await` keyword, allowing the code to wait for the promise returned by `fetch()` to resolve. The resolved response object is stored in the `response` variable.
- Another `await` keyword is used to pause the execution and wait for the promise returned by the `response.json()` method. This method parses the response body as JSON. The parsed JSON data is then stored in the `data` variable.
- Finally, the fetched user data is logged to the console. If any errors occur during the execution of the async function, they are caught in the `catch` block, enabling the handling and logging of the errors.

# Conclusion

In this article, you’ve learned what asynchronous JavaScript is and how to write asynchronous JavaScript using promises and async/await. You’ve also seen how to send requests using the fetch API and async/await and how to return a response to asynchronous calls.

> In JavaScript, synchronous instructions always take precedence over asynchronous instructions. For instance, if you have a scenario with numerous console.log statements followed by a setTimeout() function with a duration of 0 milliseconds, all the console.log statements will be executed first before the setTimeout().

I hope this article was informative? You can give it a like or a comment on what you think. 

I'm available on [Twitter](https://twitter.com/dde_olla), [LinkedIn](https://www.linkedin.com/in/adeola-ajiboso/), or [GitHub](https://github.com/Ajiboso-Adeola). Keep an eye out for my upcoming blog post, in which I'll go over another important area of web development. As a developer, I'm glad to provide additional information. Until then, happy coding, and take care!


# Resources

Here are some blogs/post I read as a reference, you should check them out:

-  [Asynchronous JavaScript (JS) Demystified](https://dev.to/thanhtr99270163/asynchronous-javascript-js-demystified-3b8j) By [Thanh Truong's](https://dev.to/thanhtr99270163/asynchronous-javascript-js-demystified-3b8j) 

- [JavaScript Async/Await Tutorial – Learn Callbacks, Promises, and Async/Await in JS by Making Ice Cream 🍧🍨🍦](https://www.freecodecamp.org/news/javascript-async-await-tutorial-learn-callbacks-promises-async-await-by-making-icecream/) By [Joy Shaheb](https://www.freecodecamp.org/news/javascript-async-await-tutorial-learn-callbacks-promises-async-await-by-making-icecream/)