Home > Web Front-end > JS Tutorial > How to Manage Multiple promises concurrently with Promise.all()

How to Manage Multiple promises concurrently with Promise.all()

Mary-Kate Olsen
Release: 2024-11-09 05:33:02
Original
340 people have browsed it

Asynchronous programming in JavaScript allows resource-intensive operations to run in the background without interrupting the main thread. Operations like API calls and file processes are some of the operations which should be run asynchronously.

Promises. all() is a powerful function that can manage these operations concurrently. This article will cover how to manage multiple promises concurrently with Promise.all()

Let’s dive in.

What is a Promise

A promise is an object that represents the eventual failure or completion of an asynchronous event. Let’s look at a simple promise.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});
Copy after login
Copy after login
Copy after login

A promise takes a function with two parameters, resolve and reject. In our example, the promise will resolve if the operation is successful (i.e., if the userId===1.If the operation fails the promise will be rejected.

The lifecycle of a promise starts in the pending state, and it will eventually either be fulfilled or rejected. Currently, the promise is pending. To consume the promise, we call .then() to handle the result.

The output will either be the user data(if fulfilled) or an error(if rejected).

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copy after login
Copy after login
Copy after login

Since the operation is successful, the promise will resolve.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copy after login
Copy after login

if we change the value of userId, the promise will be rejected and you will get the error User not found

Suppose you had multiple promises, you would handle each promise independently like this:

const promise1 = new Promise((resolve, reject) => resolve(1));
const promise2 = new Promise((resolve, reject) => resolve(2));
const promise3 = new Promise((resolve, reject) => resolve(3));
promise1
  .then((value) => {
    console.log(value);
    promise2
      .then((value) => {
        console.log(value);
        promise3
          .then((value) => {
            console.log(value);
          })
          .catch((err) => {
            console.log("promise3 error", err);
          });
      })
      .catch((err) => {
        console.log("promise2 error", err);
      });
  })
  .catch((err) => {
    console.log("promise1 error", err);
  });
Copy after login

There are a few potential issues that will arise from the execution above:

  • Each promise runs after the previous one is completed. promise2 will start after promise1 resolves and promise3 will start after promise2 resolves; This slows down execution.

  • The nested structure in the .then chaining results in “callback hell”, making the code harder to read and maintain.

  • Each error is handled independently which adds to more complexity.

A better approach would be to use Promise.all(),which allows promises to run at the same time, hence improving performance and error handling

Enhancing Asynchronous Operations with Promise.all()

Promise.all() takes an iterable of promises and returns a single promise. The syntax looks like this:

Promise.all(iterable)
Copy after login

If we use Promise.all() In our earlier example, we have something like this:

Promise.all([promise1, promise2, promise3])
  .then((values) => {
    console.log(values);
  })
  .catch((err) => {
    console.log("promise all error", err);
  });
Copy after login

As you can see, this approach is cleaner and easier to understand.

JavaScript is a single-threaded language, meaning that each piece of code waits for the previous one to complete before going to the next.

So if JavaScript is single-threaded, how does Promise.all()handle multiple promises?

Promise.all()operates on the concurrency principle, which means that all the promises will start executing not necessarily at the same moment, but initiated without waiting for one to complete before starting the next.

Promise.all()only resolves when all the promises in the iterable are fulfilled, However, if any of the promises in the iterable rejects, Promise.all() will reject immediately and ignore the result of the remaining promises.

Practical Examples

Promise.all() excels in scenarios where you need to perform multiple independent asynchronous operations and wait for all of them to finish before proceeding.

Let’s look at some of these examples where Promise.all() can be used to improve efficiency in real-world applications.

1.Fetching Data from multiple API’s

Consider a scenario where you are working on an application that fetches data from two different APIs simultaneously.

Let’s attempt to fetch the data sequentially from multiple API’s and also log the time taken to finish the request.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});
Copy after login
Copy after login
Copy after login

Here is the output:

How to Manage Multiple promises concurrently with Promise.all()

The time taken to process the request is 50.36 ms. This execution time can be improved. To illustrate the benefits of concurrency, Let’s compare the approach using Promise.all()

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copy after login
Copy after login
Copy after login

Here we are using Promise.all() to run multiple asynchronous operations concurrently. Promise.all()will take an array of promises and return a single promise when all the promises have resolved.

Here is the output.

How to Manage Multiple promises concurrently with Promise.all()

From the output, we can see that using Promise.all() is slightly more efficient: This improvement occurs because Promise.all()allows both operations to start simultaneously, rather than waiting for one to finish before starting the other.

In real-world applications with more complex operations or additional API calls, the performance gains from using Promise.all()can be even more significant.

However, if you want to wait for all the promises to settle, regardless of whether they fulfill or reject, you can use Promise.allSettled()

  1. Sending Multiple Chunks of Data Suppose you have an array of text chunks that represent customer feedback or reviews and you need to analyze the sentiment of each chunk by sending it to an external API for analysis.

In this case, all the data needs to be sent at the same time. In this case, you can use Promise.all() and send all the requests concurrently, and then wait for all of them to resolve before getting the results.

For example, suppose we needed to analyse this sample data:

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});
Copy after login
Copy after login
Copy after login

In this case, all the data needs to be sent at once; sending data sequentially will be time-consuming. Instead, we will use Promise.all() to initiate multiple API calls simultaneously.

You will have something like this:

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copy after login
Copy after login
Copy after login

3. Reading and Processing multiple files concurrently.

Suppose you have an application that accepts bulk uploads from users. After taking all the necessary measures to validate the files, you can use Promise.all()to perform multiple file reads in parallel. This is far more efficient than reading each file one by one in a sequential manner.

Without Promise.all(), you would have to wait for each file to be read completely before reading the next file. This would lead to more processing time, especially if you have a larger number of files.

However, with Promise.all(), all file reading operations are initiated simultaneously, leading to considerable time savings and a great user experience.

const userId = 1;
let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (userId === 1) {
      resolve({ name: "John Doe", email: "john@example.com" });
    } else {
      reject(new Error("User not found"));
    }
  }, 1000);
});

promise
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err);
  });
Copy after login
Copy after login

It’s also important to note that when reading many large files simultaneously, you should be mindful of potential memory considerations.

Summary

In conclusion, Promise.all() offers a lot of benefits which are summarised below

Cleaner Code: Promise.all()makes your code easier to understand since you don’t have nested .then() chains. Requests are handled in a single .then() block.

Efficient: By making requests concurrently, your application’s overall performance improves, as the total time required to fetch the data is reduced.

Level Up Your JavaScript

Get practical JavaScript tips and code snippets delivered to your inbox. Join 1000 developers who write better code.

The above is the detailed content of How to Manage Multiple promises concurrently with Promise.all(). For more information, please follow other related articles on the PHP Chinese website!

source:dev.to
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template