Async Await in JavaScript

Understanding Async and Await in JavaScript: A Beginner’s Guide

If you’re new to coding, you’ve probably heard the term async/await floating around. It might sound complex, but trust me, once you get the hang of it, it can make your JavaScript code much easier to understand and work with. Let’s break it down step by step!


What is Asynchronous Programming?

Before diving into async and await, it's important to understand asynchronous programming. In simple terms, asynchronous programming allows JavaScript to perform multiple tasks at the same time without blocking the execution of other tasks.

Imagine you’re baking a cake. While the cake is baking (a task that takes time), you can go ahead and clean up the kitchen (another task). You don’t need to wait for the cake to bake before you start cleaning. In JavaScript, we use asynchronous programming to handle tasks like data fetching, timers, or reading files, all without making the rest of the code wait.


Promises: The First Step Toward Asynchronous Code

In JavaScript, asynchronous operations are usually handled using Promises. A promise is like a promise you make to someone: you tell them that you will do something (like fetch data from a server), and once it’s done, you’ll either fulfill it (give the result) or fail (give an error).

A promise can be in one of these states:

  • Pending: The task is still in progress.
  • Fulfilled: The task is complete, and we have the result.
  • Rejected: The task failed, and there’s an error.

Here’s how you might use a promise:

let promise = new Promise((resolve, reject) => {
  let isTaskDone = true;
  if (isTaskDone) {
    resolve("Task completed successfully!");
  } else {
    reject("There was an error.");
  }
});
 
promise.then(result => {
  console.log(result);  // Task completed successfully!
}).catch(error => {
  console.log(error);   // There was an error.
});

Introducing Async and Await

Now, let’s talk about async and await—two keywords that make working with promises a lot more straightforward. These keywords simplify how we write asynchronous code.

What is the async Keyword?

The async keyword is used to declare a function as asynchronous. This means that the function will always return a promise, and you can use await inside it to pause the execution of the code until the promise resolves.

async function fetchData() {
  return "Data fetched successfully!";
}
 
fetchData().then(result => console.log(result));  // Data fetched successfully!

Notice that even though fetchData() seems to return a normal value ("Data fetched successfully!"), it actually returns a promise, and .then() is used to get the result when the promise is fulfilled.

What is the await Keyword?

The await keyword can only be used inside an async function. It pauses the execution of the function until the promise is resolved (or rejected). It’s like telling JavaScript, “Wait here until this promise is done, and then continue with the next task.”

async function getData() {
  let result = await fetchData();  // Wait until fetchData() is complete
  console.log(result);  // This will log the result after the promise is resolved
}
 
getData();  // Data fetched successfully!

How Async/Await Makes Code Cleaner

Using async and await results in cleaner, more readable code. Without these keywords, working with promises often leads to "callback hell," where you have nested .then() and .catch() methods that can become hard to follow.

Example Without Async/Await:

fetchData()
  .then(result => {
    return processResult(result);
  })
  .then(processed => {
    return saveData(processed);
  })
  .then(() => {
    console.log("All tasks completed!");
  })
  .catch(error => {
    console.log("An error occurred:", error);
  });

Example With Async/Await:

async function executeTasks() {
  try {
    let result = await fetchData();
    let processed = await processResult(result);
    await saveData(processed);
    console.log("All tasks completed!");
  } catch (error) {
    console.log("An error occurred:", error);
  }
}
 
executeTasks();

Notice how much cleaner and more readable the async/await version is? No more nested .then() chains!


Error Handling with Async/Await

When dealing with promises, it’s important to handle errors. With async/await, error handling becomes easier because you can use a simple try...catch block, just like in synchronous code.

Here’s an example:

async function fetchData() {
  throw new Error("Something went wrong!");
}
 
async function getData() {
  try {
    let result = await fetchData();  // Wait for fetchData to complete
    console.log(result);
  } catch (error) {
    console.log("Caught an error:", error.message);  // Handle the error
  }
}
 
getData();  // Caught an error: Something went wrong!

Practical Example: Fetching Data from an API

Let's bring all the concepts together with a practical example: fetching data from a real API. Here's how you can use async/await to make the code easier to work with: `


All the Code You Need to Practice

JavaScript Code Runner on: async

IndGeek provides solutions in the software field, and is a hub for ultimate Tech Knowledge.