1. Home
image

JavaScript Tutorial Concepts - From Beginner to Pro

Learn JavaScript from scratch! Our tutorial covers basics to advanced concepts. Start learning today!

  • 24
  • 9 Hours
right-top-arrow
14

JavaScript Async Await

Updated on 08/08/2024246 Views

Before async/await, Promises were the primary tool for asynchronous work in JavaScript. While Promises are powerful, they can lead to code that chains .then() calls or nests many callbacks. Here's where async/await shines, providing us with a better way.

Before we delve into await and async in JavaScript, I would first like to go back to their origins, asynchronous programming. I’ll first touch upon what exactly asynchronous programming is and then, I will discuss the async and await keywords in this JavaScript async await tutorial.

We will also look at some async await JavaScript example programs to understand these keywords and their methods properly.

Asynchronous Programming in JS

JavaScript, especially when running in a web browser environment, has a unique challenge. It's single-threaded, meaning it has one line of execution at a time. If any task (fetching data, responding to a button click, etc.) takes a long time, it would freeze the entire webpage!

Asynchronous programming is the pattern to tackle this. It enables us to start a potentially long-running operation and tell JavaScript, "Go about your business, I'll let you know when this is ready." This prevents the webpage from locking up.

Promises

Think of a Promise as an IOU where:

  • Pending: When an asynchronous operation starts, it's pending.
  • Fulfilled: The operation successfully completed, and the promise now holds the resulting value.
  • Rejected: Something went wrong, and the promise holds an error.

JavaScript async await: Syntactic Upgradation

JavaScript async await lets us write asynchronous code that resembles the style of straightforward, step-by-step (synchronous) code. This often makes the logic much easier to follow.

To master async/await, we'll need to grasp:

  • The async keyword: How it turns a function into a 'Promise factory'.
  • The await keyword: How it works within an async function to pause and wait for a Promise's result.

The async Keyword

When you add the word async before a function declaration (or arrow function), you mark a function as asynchronous and the function now implicitly returns a Promise.

Even if the function directly returns a regular value (like a number), it will actually be wrapped in a resolved Promise. Also, I would like to mention that we are able to use the await keyword within the function's body.

Examples:

// Regular function

async function fetchData() {

  // ... some asynchronous operation here ...

}

// Arrow Function 

const fetchData2 = async () => {

  // ... some asynchronous operation here ...

}

The await Keyword

The await keyword can only be used within a function that has been declared as async. await can only be put in front of an expression that returns a Promise.

This in turn causes the async function to pause its execution until the Promise it's waiting on either resolves or rejects. If the Promise resolves, await unwraps the fulfilled value and the async function continues. If the Promise rejects, an error is thrown.

Example:

async function processData() {

    const rawResponse = await fetch('https://api.example.com/data'); 

    const jsonData = await rawResponse.json(); 

    // Do something with jsonData 

Practical Examples of JavaScript async await

Here are some practical JavaScript async await example programs of JavaScript async await methods:

1. Fetching Data from an API

Code:

async function getMovieData(title) {

  try {

    const response = await fetch(`https://www.upGrad.com/?t=${title}&apikey=YOUR_API_KEY`);

    if (!response.ok) {

      throw new Error(`HTTP Error: ${response.status}`); 

    }

    const data = await response.json();

    return data;

  } catch (error) {

    console.error('Error fetching movie:', error);

  }

}

// Using it:

getMovieData('Back to the Future')

  .then(movie => console.log(movie))

  .catch(error => console.error('Something went wrong:', error));  

Key points in the above code:

  • Network requests: Ideal for fetch.
  • try...catch: Cleanly handles both network errors and potential JSON parsing issues.

2. Working with Timers

Code:

async function delayedMessage(message, delayMs) {

  return new Promise(resolve => {

    setTimeout(() => {

      resolve(message);

    }, delayMs);

  });

}

async function demoTimeout() {

  const message = await delayedMessage("Hello after 3 seconds!", 3000);

  console.log(message); 

}

demoTimeout(); 

Key points in the above code:

  • Wrapping setTimeout: Makes working with timer-based delays more intuitive.

3. Reading Files (async and await in Node JS)

Code:

const fs = require('fs/promises'); // Node.js promises-based file I/O

async function readFileContents(filePath) {

  try {

    const data = await fs.readFile(filePath, 'utf-8');

    return data;

  } catch (error) {

    console.error('Error reading file:', error);

  }

}

// Using it:

readFileContents('data.txt')

  .then(contents => console.log(contents))

  .catch(error => console.error('File issue:', error));  

Key points in the above code:

  • Node.js: File system I/O is inherently asynchronous in Node.js.
  • Modern libraries: Many modern libraries provide Promise-based APIs, making them perfect for async/await.

If you wish to master essential JS concepts like the JavaScript async await methods, you can enroll in any of the full stack development courses by upGrad.

Code Comparisons: Promise Chains vs. Async/Await

Let's compare the code and approach between Promise chains and the use of async and await in javascript. We will be fetching data from an API and then processing the result.

Promise Chain Approach

JavaScript async await Approach

Code:

async function fetchDataAndProcess() {

  try {

    const response = await fetch('https://api.upgrad.com/data');

    const data = await response.json();

    console.log('Processed Data:', data);

  } catch (error) {

    console.error('Error:', error); 

  }

}

Now that we have gone through both of the Promise async await JavaScript examples, I want to point out that the async/await approach avoids nested .then blocks. Our logic appears more linear in this approach. Also, the code looks closer to how we'd conceptually describe the task (fetch, then process).

Error handling with async/await is also easy with the try...catch structure that works perfectly with JavaScript async await. If an error is thrown at any point within the try block in our async function, the returned Promise is automatically rejected, and the catch block handles it.

Concurrent Async Operations

Often, you'll need to perform multiple asynchronous tasks where the order in which they finish doesn't matter. Fetching data from multiple APIs simultaneously is a classic example. Doing this one by one would be unnecessarily slow.

How Promise.all Helps

Promise.all is your concurrency tool. Here is the process behind it:

  1. Takes an array of Promises: Promise.all([promise1, promise2, ...])
  2. Returns a single Promise: This special Promise resolves only when all the promises you gave it resolve, or rejects immediately if any of them reject.
  3. Result array: If successful, the resolved value of the Promise returned by Promise.all is an array containing the results of each individual Promise in the order you provided them.

Example:

async function fetchMultiple() {

  try {

    const [response1, response2] = await Promise.all([

      fetch('https://api.github.com/users/defunkt'), // Fetch user data

      fetch('https://api.twitter.com/1.1/users/show.json?screen_name=jack') // Fetch Twitter data

    ]);

    const githubData = await response1.json();

    const twitterData = await response2.json();

    // Do something with both githubData and twitterData

  } catch (error) {

    console.error("Fetching failed:", error);

  }

}

The GitHub and Twitter requests will likely run in parallel, saving you time. If either fetch fails, the Promise from Promise.all rejects, triggering your catch.

On a side note, if you need the result of one operation to kick off another, this isn't the tool. In that case, we should stick to regular await chains. If you need results as they arrive, even if some fail, you'll need a more custom solution.

Wrapping Up

I want you to remember that async/await is mainly about readability. Under the hood, it still relies on Promises. Don't expect miracles, but modern JavaScript engines optimize async/await code very well.

Async/await offers a significant improvement for writing asynchronous JavaScript code. By letting us express asynchronous logic in a style closer to synchronous code, async/await often makes it much easier to understand the flow of your program at a glance.

Also, I want to mention that the best way to truly master JavaScript async await methods is to get your hands dirty and find asynchronous tasks in your own projects. You can also explore libraries or APIs that make heavy use of Promises. Practice translating their usage into sleek async/await patterns.

If you wish to master technologies such as JavaScript, you can enroll in upGrad’s software engineering courses.

Frequently Asked Questions

1. What is async await in JavaScript?
Async/await provides a cleaner way to write asynchronous code that resembles synchronous code, improving readability.

2. Is async await just a promise?
No, it's syntactic sugar built on top of Promises. Async/await makes working with Promises easier but still relies on them under the hood.

3. What is the difference between async and await?

  • async: Marks a function as asynchronous, making it implicitly return a Promise.
  • await: Can only be used within an async function, pauses execution until a Promise resolves and then unwraps the value.

4. Why we use async and await in node JS?
Node.js relies heavily on asynchronous operations (file I/O, network requests, etc.). Async/await makes managing this asynchronous nature smoother compared to callbacks or Promise chains.

5. How does async await work?
An async function always returns a Promise. The await keyword pauses execution within the async function until the awaited Promise settles (resolves or rejects).

6. Why await is used in JavaScript?
To make asynchronous code look more like synchronous code, making your code easier to read and reason about.

7. What is one benefit of using async await?
Improved code readability and easier error handling using try...catch blocks.

8. Can I use await without async?
No. The await keyword can only be used inside a function declared with async.

9. When should I use async?
Anytime you have code that needs to wait for the completion of an asynchronous operation before proceeding.

image

mukesh

Working with upGrad as a Senior Engineering Manager with more than 10+ years of experience in Software Development and Product Management.

Get Free Career Counselling
form image
+91
*
By clicking, I accept theT&Cand
Privacy Policy
image
Join 10M+ Learners & Transform Your Career
Learn on a personalised AI-powered platform that offers best-in-class content, live sessions & mentorship from leading industry experts.
right-top-arrowleft-top-arrow

upGrad Learner Support

Talk to our experts. We’re available 24/7.

text

Indian Nationals

1800 210 2020

text

Foreign Nationals

+918045604032

Disclaimer

upGrad does not grant credit; credits are granted, accepted or transferred at the sole discretion of the relevant educational institution offering the diploma or degree. We advise you to enquire further regarding the suitability of this program for your academic, professional requirements and job prospects before enr...