JavaScript

coding learning websites codepractice

JS Basics

JS Variables & Operators

JS Data Types & Conversion

JS Numbers & Math

JS Strings

JS Dates

JS Arrays

JS Control Flow

JS Loops & Iteration

JS Functions

JS Objects

JS Classes & Modules

JS Async Programming

JS Advanced

JS HTML DOM

JS BOM (Browser Object Model)

JS Web APIs

JS AJAX

JS JSON

JS Graphics & Charts

JavaScript Async/Await


Async and Await were introduced in ES2017 to make asynchronous JavaScript code easier to read and write. They are built on top of Promises but allow you to write asynchronous code that looks and behaves like synchronous code.

Before async/await, handling asynchronous operations often required callbacks or Promise chains, which could become difficult to read and maintain. async/await solves this problem by simplifying asynchronous control flow.

What is async Function?

An async function is a function that always returns a Promise, regardless of whether you explicitly return a Promise or a value.

// Example of async function
async function greet() {
  return "Hello, Async!";
}

// Calling async function
greet().then(message => console.log(message)); // Logs: Hello, Async!
  • The return value "Hello, Async!" is automatically wrapped in a resolved Promise.

What is await Function?

The await keyword can only be used inside an async function. It pauses the execution of the function until the Promise resolves and returns its value.

async function fetchMessage() {
  let message = await Promise.resolve("Message received!");
  console.log(message);
}

fetchMessage(); // Logs: Message received!
  • Here, the function waits for the Promise to resolve before logging the message.

Example: Fetching Data with Async/Await

// Simulating a fetch operation with a promise
function getData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      let success = true;
      if (success) {
        resolve({ id: 1, name: "Alice" });
      } else {
        reject("Failed to fetch data");
      }
    }, 2000); // Simulate 2-second delay
  });
}

// Using async/await to handle the promise
async function fetchUser() {
  try {
    const user = await getData(); // Waits for promise to resolve
    console.log("User:", user);
  } catch (error) {
    console.error("Error:", error); // Catches rejection if promise fails
  } finally {
    console.log("Fetch operation completed"); // Always runs
  }
}

fetchUser();
  • try/catch is used for error handling instead of .catch() with Promises.

  • finally runs regardless of success or failure.

Chaining Async Operations

Async/await allows chaining multiple asynchronous operations in a readable way.

function step1() {
  return new Promise(resolve => setTimeout(() => resolve("Step 1 done"), 1000));
}

function step2() {
  return new Promise(resolve => setTimeout(() => resolve("Step 2 done"), 1000));
}

function step3() {
  return new Promise(resolve => setTimeout(() => resolve("Step 3 done"), 1000));
}

async function processSteps() {
  try {
    const result1 = await step1();
    console.log(result1);

    const result2 = await step2();
    console.log(result2);

    const result3 = await step3();
    console.log(result3);
  } catch (error) {
    console.error("Error:", error);
  }
}

processSteps();
  • Each step waits for the previous one to complete, maintaining the correct sequence.

Handling Multiple Promises in Parallel

You can use await with Promise.all() to run multiple promises concurrently.

async function fetchMultiple() {
  const promise1 = Promise.resolve("Data 1");
  const promise2 = Promise.resolve("Data 2");
  const promise3 = Promise.resolve("Data 3");

  const results = await Promise.all([promise1, promise2, promise3]); // Wait for all to resolve
  console.log(results); // Logs: ["Data 1", "Data 2", "Data 3"]
}

fetchMultiple();
  • This approach improves performance for independent asynchronous tasks.

Error Handling in Async/Await

Errors in an async function are automatically converted into rejected Promises. Use try/catch for handling them.

async function fetchWithError() {
  try {
    const data = await Promise.reject("Something went wrong!");
    console.log(data);
  } catch (err) {
    console.error("Caught error:", err); // Handles the rejected promise
  }
}

fetchWithError();
  • This is simpler and more readable than chaining .catch() with Promises.

Advantages of Async/Await

  • Makes asynchronous code readable and linear like synchronous code.

  • Easier to debug, since stack traces are simpler than deeply nested Promise chains.

  • Works seamlessly with Promises and Promise combinators (all, race, etc.).

  • Reduces callback hell and improves maintainability.

Real-World Example: API Fetch

async function fetchPost() {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts/1"); // Wait for fetch
    const post = await response.json(); // Wait for response to convert to JSON
    console.log("Post:", post);
  } catch (error) {
    console.error("Error fetching post:", error);
  } finally {
    console.log("API request finished");
  }
}

fetchPost();
  • This is how modern applications handle HTTP requests cleanly.

  • No .then() chains are needed, and the flow is easier to follow.

Summary of the Tutorial

  • async functions always return a Promise.

  • await pauses execution until the Promise resolves and returns its value.

  • Use try/catch for error handling and finally for cleanup tasks.

  • Async/await makes asynchronous code cleaner, readable, and easier to maintain.

  • Combined with Promise.all() or other Promise utilities, it provides powerful control over async operations.

Mastering async/await is essential for modern JavaScript development, especially when working with APIs, timers, events, or complex asynchronous workflows.


Practice Questions

  1. Create an async function that waits for a Promise resolving "Hello World" after 2 seconds and logs it.

  2. Write an async function that fetches data from https://jsonplaceholder.typicode.com/posts/1 using fetch and logs the JSON response. Handle errors using try/catch.

  3. Create two Promises that resolve after 1 second and 2 seconds respectively. Use async/await to log both results sequentially.

  4. Write an async function that calls three functions returning Promises: step1(), step2(), step3(). Log each step in order.

  5. Create an async function that intentionally rejects a Promise. Use try/catch to catch and log the error.

  6. Write an async function that fetches multiple URLs (at least 3) using Promise.all() and logs all responses together.

  7. Create an async function that uses await with setTimeout wrapped in a Promise to simulate a 3-second delay, then logs "Delay finished".

  8. Write an async function that fetches a post from an API and uses finally to log "Operation completed" regardless of success or failure.

  9. Create an async function that performs two independent async tasks concurrently using Promise.all(), then logs the results.

  10. Write an async function that demonstrates sequential execution by awaiting multiple Promises one after another, logging the time each Promise resolves to show the order.


JavaScript

online coding class codepractice

JS Basics

JS Variables & Operators

JS Data Types & Conversion

JS Numbers & Math

JS Strings

JS Dates

JS Arrays

JS Control Flow

JS Loops & Iteration

JS Functions

JS Objects

JS Classes & Modules

JS Async Programming

JS Advanced

JS HTML DOM

JS BOM (Browser Object Model)

JS Web APIs

JS AJAX

JS JSON

JS Graphics & Charts

Go Back Top