Async / Await

  • This lesson explains how async/await improves asynchronous code readability.
  • Introduction to Async / Await

    In modern JavaScript applications, many operations take time, such as:

    • Fetching data from a server

    • Reading files

    • Waiting for user actions

    • Calling APIs

    • Performing background tasks

    Handling these operations without freezing the UI is possible using asynchronous JavaScript.

    Earlier, JavaScript handled async operations using:

    • Callbacks

    • Promises

    While Promises improved code readability, they still caused complex chaining.

    To solve this problem, JavaScript introduced async / await.

    What is Async / Await ?

    Async / Await is a modern JavaScript feature built on top of Promises, which allows us to write asynchronous code that looks simple and synchronous.

    Simple Definition

    async / await allows asynchronous code to be written in a synchronous-like style, making it easier to read, write, and debug.

    Why Async / Await Was Introduced

    Problems with callbacks and promises:

    • Nested callbacks (callback hell)

    • Long .then() chains

    • Hard to read and debug

    Async / await solves these problems by:

    • Improving readability

    • Reducing complexity

    • Making error handling easier

    Relationship Between Promise and Async / Await

    • async functions always return a Promise

    • await pauses execution until the Promise resolves

    • Async / await is just syntactic sugar over Promises

    The async Keyword

    What Does async Do ?

    The async keyword is used to define an asynchronous function.

    async function myFunction() {

      return "Hello";

    }

    Even though it looks like a normal return, JavaScript automatically wraps it inside a Promise.

JavaScript Async Function with Promise

This code demonstrates how an async function automatically returns a Promise and its result is handled using .then().

async function greet() {
  return "Welcome";
}

greet().then(result => {
  console.log(result);
});
  • The await Keyword

    What Does await Do ?

    The await keyword is used inside an async function to pause execution until a Promise is resolved.

    let result = await somePromise;

    Important points:

    • await can only be used inside async functions

    • It waits for Promise resolution

    • It does not block the main thread

JavaScript Async/Await with Promise Example

This code demonstrates how async/await is used to handle Promises in a more readable way by waiting for asynchronous data before continuing execution.

function fetchData() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve("Data received");
    }, 2000);
  });
}

async function showData() {
  let data = await fetchData();
  console.log(data);
}

showData();
  • Execution Flow Explanation

    1. showData() is called

    2. fetchData() returns a Promise

    3. await pauses execution inside showData()

    4. After 2 seconds, Promise resolves

    5. Execution resumes and logs data

  • Async / Await vs Promises

    Using Promises

JavaScript Promises vs Async/Await (Promise Handling)

This code demonstrates handling asynchronous operations using Promises with .then() and .catch() for success and error handling.

fetchData()
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.log(error);
  });

JavaScript Async/Await Error Handling Example

This code demonstrates how async/await with try...catch is used to handle asynchronous operations and errors in a cleaner way than Promises.

async function getData() {
  try {
    let data = await fetchData();
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}
  • Async / await is cleaner and easier to understand.

    Error Handling with Async / Await

    Using try...catch

JavaScript Fetch API with Async/Await

This code demonstrates how to fetch data from an API using async/await and handle the response and errors using try...catch.

async function fetchUser() {
  try {
    let response = await fetch("https://api.example.com/user");
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.log("Error occurred:", error);
  }
}
  • Errors are handled just like synchronous code.

JavaScript Async/Await Without Error Handling

This code demonstrates an async function where a rejected Promise is awaited without try...catch, which can cause an unhandled error.

Without try...catch 
async function test() {
  let result = await Promise.reject("Failed");
}
  • This causes an unhandled promise rejection.

    Multiple await Statements

    Async functions can contain multiple await calls.

JavaScript Sequential Async/Await Execution

This code demonstrates how multiple asynchronous tasks are executed one after another using async/await in a sequential flow.

async function processData() {
  let a = await firstTask();
  let b = await secondTask();
  let c = await thirdTask();
  console.log(a, b, c);
}
  • Each await waits for the previous one to finish.

    Parallel Execution Using Promise.all()

    Awaiting tasks one by one can be slow.

JavaScript Parallel Execution with Promise.all

This code demonstrates how multiple asynchronous tasks run in parallel using Promise.all and return all results together.

async function loadAll() {
  let results = await Promise.all([
    taskOne(),
    taskTwo(),
    taskThree()
  ]);

  console.log(results);
}
  • This runs tasks in parallel.

    Async / Await with Fetch API

JavaScript Fetch API Example with Async/Await

This code demonstrates how to fetch data from an API using async/await and convert the response into JSON format.

async function getPosts() {
  let response = await fetch("https://jsonplaceholder.typicode.com/posts");
  let posts = await response.json();
  console.log(posts);
}

getPosts();
  • This is a very common real-world use case.

    Common Mistakes

    • Using await outside an async function

    • Forgetting error handling

    • Expecting await to block the entire program

    • Writing sequential awaits unnecessarily

    • Not understanding that async returns a Promise

    Best Practices for Async / Await

    • Always use try...catch

    • Use Promise.all() for independent tasks

    • Keep async functions small

    • Avoid mixing .then() with await

    • Handle network and runtime errors properly

    Real-World Use Cases

    • API calls

    • Authentication systems

    • Data loading

    • File handling

    • Timers and delays

    • Backend communication