Your Page Title
🔍

    JavaScript async/await

    Introduction

    Modern JavaScript has made asynchronous programming much easier and more readable with the introduction of async and await in ES2017 (ES8). These keywords are built on top of Promises and allow developers to write asynchronous code that looks and behaves like synchronous code.

    If you’ve ever struggled with chained .then() calls or callback hell, async/await is the clean, readable solution you’ve been looking for.


    What Are async and await?

    • async: Declares a function as asynchronous, meaning it automatically returns a Promise.
    • await: Pauses the execution of the async function until the Promise is resolved or rejected.

    Together, these allow you to write asynchronous code that reads almost like a story—top to bottom, left to right.


    Basic Syntax

    Example:

    javascriptCopyEditasync function greet() {
      return "Hello";
    }
    
    greet().then((message) => console.log(message)); // Output: Hello
    

    Even though greet() looks like a normal function, it returns a Promise because of the async keyword.


    Using await

    The real power comes when you use await to pause for a Promise:

    javascriptCopyEditfunction delay(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    async function run() {
      console.log("Start");
      await delay(2000); // Waits for 2 seconds
      console.log("End after 2 seconds");
    }
    
    run();
    

    Output:

    pgsqlCopyEditStart
    (wait 2 seconds)
    End after 2 seconds
    

    The function waits for the Promise returned by delay() to resolve before continuing.


    Real-World Example: Fetching Data

    Here’s how async/await is used in a real application, such as fetching data from an API:

    javascriptCopyEditasync function getUser() {
      try {
        const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error("Error fetching user:", error);
      }
    }
    
    getUser();
    

    Explanation:

    • fetch returns a Promise for the HTTP response.
    • response.json() also returns a Promise.
    • We await both to get the final user data.
    • Errors are handled with try/catch.

    Why Use async/await?

    Benefits:

    • Cleaner syntax than .then() chains
    • Easier error handling with try/catch
    • More readable and maintainable
    • Works seamlessly with existing Promise-based APIs

    Comparison:

    With Promises:

    javascriptCopyEditfetch(url)
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(err => console.error(err));
    

    With async/await:

    javascriptCopyEditasync function getData() {
      try {
        const response = await fetch(url);
        const data = await response.json();
        console.log(data);
      } catch (err) {
        console.error(err);
      }
    }
    

    Both do the same thing, but the async/await version is more readable.


    Sequential vs. Parallel Execution

    Sequential:

    javascriptCopyEditasync function run() {
      await task1();
      await task2(); // Waits for task1 to finish first
    }
    

    Parallel (better performance):

    javascriptCopyEditasync function run() {
      const t1 = task1();
      const t2 = task2();
      await t1;
      await t2;
    }
    

    If tasks are independent, start them without await and then await them together to improve performance.


    Error Handling with try/catch

    javascriptCopyEditasync function getData() {
      try {
        const res = await fetch("https://invalid-url");
        const data = await res.json();
        console.log(data);
      } catch (error) {
        console.error("Caught an error:", error);
      }
    }
    

    Just like synchronous code, errors can be caught with try/catch, making debugging easier.


    Tips & Best Practices

    • Use async/await only inside async functions.
    • Wrap your logic in try/catch blocks to handle errors.
    • Avoid using await in loops when possible—use Promise.all() for parallelism.
    • Don’t block the main thread with long await chains unless necessary.

    Conclusion

    async/await is one of the most powerful additions to JavaScript for writing cleaner, more readable asynchronous code. It builds on top of Promises but removes much of the complexity associated with chaining and nesting.

    Summary:

    • async turns a function into a Promise.
    • await pauses execution until the Promise resolves.
    • Use try/catch to handle errors.
    • It simplifies asynchronous logic significantly.

    By mastering async/await, you’ll write more efficient and maintainable JavaScript—whether you’re building APIs, UI apps, or working with databases.