WTF is Asynchronous JavaScript: async/await vs .then()

WTF is Asynchronous JavaScript: async/await vs .then()

Learn the differences between .then() and async/await in JavaScript for handling asynchronous operations efficiently.

Introduction

Hey there! Welcome back to the new blog post in the "WTF is JavaScript" series.

In today's article, we will understand the asynchronous capabilities of JavaScript. Also, we will learn about how to use .then() and async/await in your code.

WTF is JavaScript Series 👈🏻

In this series, we are exploring key modern JavaScript concepts, one topic at a time. Checkout the series to find more such insightful content and improve your JavaScript skills.

Is JavaScript Synchronous or Asynchronous?

JavaScript is both synchronous and asynchronous, depending on how it's used. This duality arises from JavaScript's single-threaded execution model and its need to handle tasks that may take some time to complete, such as fetching data from a server or reading a file.

  1. Synchronous JavaScript:

    • JavaScript is inherently synchronous by nature, which means it executes code line by line, one after the other.

    • Synchronous operations block the execution of subsequent code until the current operation is completed. For example, if you have a long-running calculation, it will prevent other tasks from running until it's finished.

  2. Asynchronous JavaScript:

    • JavaScript also supports asynchronous operations to prevent blocking. This is essential for tasks like making HTTP requests, reading files, or waiting for user input.

    • Asynchronous operations allow JavaScript to start a task, and then move on to other tasks without waiting for the first task to complete. When the asynchronous task finishes, it triggers a callback function or resolves a promise.

It means that JavaScript is synchronous by default to ensure predictable execution but provides mechanisms like callbacks, promises, and async/await to handle asynchronous operations efficiently and maintain responsiveness in web applications.

Understand async programming with .then() and async/await

This is where .then() and async/await come into play. They provide structured ways to work with asynchronous operations, allowing developers to write code that's easier to understand, manage, and maintain while ensuring responsiveness.

The .then() Approach: Old But Gold

Let's start with the .then() approach, which is based on Promises—a JavaScript feature introduced to handle asynchronous operations.

Suppose you want to fetch and display a list of user names from an API. Here's how you might use .then():

fetch('https://jsonplaceholder.typicode.com/users')
  .then(response => response.json())
  .then(data => {
    const usernames = data.map(user => user.username);
    console.log(usernames);
  })
  .catch(error => console.error(error));

Output:

["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]

Here's how it works:

  1. We fetch data from the API.

  2. We use .then() to handle the response.

  3. We convert the response to JSON.

  4. We log the data or handle errors with .catch().

Problems with .then() - Callback Hell

While .then() is useful, but it can become problematic when you have multiple asynchronous tasks or deeply nested operations. This situation is often referred to as "callback hell" because the code becomes difficult to read and maintain.

example:

Imagine you need to fetch user data and their posts, and then log both. Here's how it might look in callback hell:

fetch('https://jsonplaceholder.typicode.com/users/1')
  .then(userResponse => userResponse.json())
  .then(userData => {
    fetch(`https://jsonplaceholder.typicode.com/posts?userId=${userData.id}`)
      .then(postsResponse => postsResponse.json())
      .then(postsData => {
        console.log('User Data:', userData);
        console.log('User Posts:', postsData);
      })
      .catch(error => console.error(error));
  })
  .catch(error => console.error(error));

As you can see, the code becomes deeply nested and challenging to follow.

Introduction to async/await: simpler way

To address the issues of callback hell and simplify asynchronous code, JavaScript introduced async/await. It allows developers to write asynchronous code in a more linear and structured way.

How async/await Helps

Here are a few key benefits of async/await:

  1. Readability: Asynchronous code can be written more like synchronous code, making it easier for developers to follow the flow of the program.

  2. Error Handling: Errors are easier to handle with try...catch blocks, leading to more robust and maintainable code.

  3. Structured: Code becomes more structured and organized, reducing the need for deeply nested callbacks.

Now, let's see how async/await works with an example.

Code Example with Output

async function fetchUsernames() {
  try {
    const response = await fetch('https://jsonplaceholder.typicode.com/users');
    const data = await response.json();
    const usernames = data.map(user => user.username);
    console.log(usernames);
  } catch (error) {
    console.error(error);
  }
}

fetchUsernames();

Here's how async/await works:

  1. We declare an async function fetchUsernames.

  2. Inside the function, we use await to pause execution until the promise is resolved.

  3. We handle success and errors using a simple try...catch block.

Output:

["Bret", "Antonette", "Samantha", "Karianne", "Kamren", "Leopoldo_Corkery", "Elwyn.Skiles", "Maxime_Nienow", "Delphine", "Moriah.Stanton"]

Why async/await shines?

As you can see, the code is more structured and easier to understand compared to the .then() approach. It reads like a series of steps, from fetching the data to logging the usernames.

It's clear, organized, and easier to handle errors. No callback hell, just smooth, readable code.

Async/await vs .then(): what to choose

When to Choose .then():

  1. Familiarity: If you or your team are already comfortable with using .then(), and the codebase predominantly uses it, sticking with it may be the simplest choice.

  2. Simple Sequences: For straightforward, single asynchronous operations, such as fetching data from an API or making a single HTTP request, .then() can provide a clear and concise way to handle the task.

  3. Chaining: .then() allows for easy chaining of multiple asynchronous operations in a linear manner, which can be effective for simpler scenarios.

When to Choose async/await:

  1. Readability: async/await code reads more like synchronous code, making it easier to understand and maintain, especially for complex asynchronous logic.

  2. Error Handling: async/await simplifies error handling with try...catch blocks, leading to cleaner and more robust code.

  3. Structured Code: If you need to work with multiple asynchronous operations, async/await provides a structured way to handle them, reducing the risk of callback hell.

  4. Variable Scope: Variables declared with await are limited to the scope of the async function, preventing accidental variable leakage.

  5. Debugging: Debugging is typically easier with async/await because the code execution follows a more predictable, linear flow.

Practical Tips for Easier Coding

  • For .then(): Give your functions clear names, so it's like reading a recipe book.

  • For async/await: Use arrow functions to make your code shorter and sweeter.

Conclusion

In this introductory article, we explored JavaScript's synchronous and asynchronous nature.

We saw how .then() and async/await are essential tools for managing asynchronous operations. .then() is useful but can lead to callback hell in complex scenarios.

In contrast, async/await simplifies asynchronous code, making it more readable and structured.

Thank you for reading!

That's it for this blog post, and stay tuned for upcoming blogs in the WTF is Javascript series. Thank you for reading this article!

If you enjoyed this article, be sure to subscribe to my newsletter to stay up-to-date with my content.

And if you need any help or have any questions, don't hesitate to comment below! I'll be happy to help you out.

Did you find this article valuable?

Support Nikhil's Blog by becoming a sponsor. Any amount is appreciated!