Scalable Business for Startups

Get the oars in the water and start rowing. Execution is the single biggest factor in achievement so the faster and better your execution.

+91 9472774549 thebytemind@gmail.com Looking for collaboration for your next creative project?

Chapter 16: Asynchronous JavaScript (Promises, Async/Await)

In this chapter, we will dive deep into asynchronous JavaScript, focusing on Promises and async/await. Handling asynchronous operations effectively is essential in JavaScript, especially when dealing with I/O-bound operations such as fetching data from APIs, working with databases, or performing tasks that take time to complete. This chapter will take you from the basics to advanced concepts of Promises and async/await, ensuring you’re well-equipped to manage asynchronous code.

Table of Contents
  1. Understanding Asynchronous Programming
  2. Introduction to Promises
  3. Creating and Using Promises
  4. Promise Methods
    • Promise.all()
    • Promise.race()
    • Promise.allSettled()
    • Promise.any()
  5. Error Handling with Promises
  6. Async Functions and await
  7. Error Handling in Async/Await
  8. Advanced Topics in Promises and Async/Await
    • Sequential vs. Parallel Execution
    • Combining Promises and Async/Await
  9. Practical Examples
1. Understanding Asynchronous Programming

In JavaScript, asynchronous programming allows you to execute time-consuming tasks without blocking the main thread. Instead of waiting for a task to finish, JavaScript can continue executing the next lines of code, making your applications faster and more responsive.

Key Concepts:
  • Single-threaded: JavaScript executes code line by line, but asynchronous programming allows it to "wait" for tasks while still executing other code.
  • Event Loop: Responsible for managing asynchronous tasks by pushing them back to the main execution thread once they’re ready.
2. Introduction to Promises

A Promise is an object that represents the eventual completion (or failure) of an asynchronous operation. Think of it as a placeholder for a value that will be available in the future.

  • Pending: The initial state – neither fulfilled nor rejected.
  • Fulfilled: The operation completed successfully.
  • Rejected: The operation failed.
3. Creating and Using Promises

You can create a Promise using the new Promise constructor, which takes a function (executor) as its argument. This function has two parameters: resolve (to fulfill the promise) and reject (to reject it).

Example: Basic Promise
const asyncOperation = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Operation successful!");
    }, 2000);
  });
};

asyncOperation().then(result => {
  console.log(result); // "Operation successful!" after 2 seconds
});
4. Promise Methods

JavaScript provides several methods for handling multiple promises and managing complex asynchronous workflows.

Promise.all()

Runs multiple promises in parallel and waits until all of them are resolved or one fails.

const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(values => {
  console.log(values); // [3, 42, "foo"]
});
5. Error Handling with Promises

Promises use .catch() for handling errors. If an error occurs, .catch() will capture it, preventing the need for nested try/catch statements.

6. Async Functions and await

The async keyword declares an asynchronous function, which automatically returns a Promise. The await keyword pauses the function execution until the promise resolves or rejects, making asynchronous code look and behave like synchronous code.

Example: Async Function with Await
const fetchData = async () => {
  try {
    let response = await fetch("https://api.example.com/data");
    let data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
};

fetchData();
9. Practical Examples
Example: Fetching Data from an API with async/await
const fetchUserData = async () => {
  try {
    const response = await fetch("https://jsonplaceholder.typicode.com/users");
    if (!response.ok) throw new Error("Network response was not ok");
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error("Failed to fetch data:", error);
  }
};

fetchUserData();

This chapter has given you a comprehensive look into asynchronous JavaScript, covering Promises and async/await from the basics to advanced usage. With this knowledge, you can now write efficient, clean, and maintainable asynchronous code.