JavaScript Promise.allSettled() Method: How to Handle All Promises Regardless of Outcome

The JavaScript Promise.allSettled() method takes an array of promises and returns a single promise that resolves when all input promises have finished – whether they succeed or fail. Unlike Promise.all(), which rejects as soon as any promise fails, Promise.allSettled() waits for every promise to complete and returns an array detailing their status (fulfilled or rejected) and result. This makes it useful for cases where you need the outcome of all operations, even if some fail.

For example, if you’re building a dashboard that fetches data from multiple sources, some requests might fail while others succeed. Instead of discarding all results due to one failure, Promise.allSettled() lets you handle each response individually and display as much data as possible. Introduced in ES2020, it provides a more flexible way to manage multiple asynchronous tasks.


This article is part of our Mastering Asynchronous JavaScript guide, which explores everything from fundamental concepts like callbacks, Promises, and async/await to advanced techniques such as concurrency control with Promise.all, Promise.race, and other powerful patterns. To learn more and improve your asynchronous programming skills, check out the full guide here.


Understanding Promise.allSettled()

Promise.allSettled() accepts an iterable of promises (usually an array) and returns a new promise that always resolves once all input promises have settled, no matter if they succeed or fail. It never rejects, even if some promises fail. This makes it different from other combinator methods like Promise.all(), which fails entirely if any promise is rejected.

The syntax of this method is straightforward:

Promise.allSettled(promisesArray)

A great thing about Promise.allSettled() is its predictable result structure. For each promise in the input array, you receive an object containing two key pieces of information: the status of the promise (fulfilled or rejected) and either the resolved value or rejection reason.

Let’s look at a practical example to see how this works:

const userPromise = fetch('https://api.example.com/user')
  .then(res => res.json());
const postsPromise = fetch('https://api.example.com/posts')
  .then(res => res.json());
const weatherPromise = fetch('https://api.example.com/weather')
  .then(res => res.json());

Promise.allSettled([userPromise, postsPromise, weatherPromise])
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`Data ${index + 1} loaded successfully:`, result.value);
      } else {
        console.log(`Data ${index + 1} failed to load:`, result.reason);
      }
    });
  });

In this example, even if the weather API is down, your application still gets user data and posts. Each result in the array tells you exactly what happened with each promise, allowing for graceful degradation of functionality rather than complete failure.

Real-World Applications

Promise.allSettled() is useful when partial success is better than complete failure. Here’s a more complex example showing how it can be applied in a user management scenario:

// Validate a single user by checking email, username, and password
async function validateUser(user) {
  try {
    const results = await Promise.allSettled([
      validateEmail(user.email),
      checkUserExists(user.username),
      validatePassword(user.password)
    ]);

    const validationResults = {
      email: results[0],
      username: results[1],
      password: results[2]
    };

    const isValid = results.every(r => r.status === 'fulfilled');

    return { user, validationResults, isValid };
  } catch (error) {
    return { user, validationResults: {}, isValid: false, unexpectedError: error.message };
  }
}

// Extract error messages from a failed validation result
function extractErrors(validationResults) {
  return Object.fromEntries(
    Object.entries(validationResults)
      .filter(([_, v]) => v.status === 'rejected')
      .map(([field, v]) => [field, v.reason])
  );
}

// Process a batch of users and validate them asynchronously
async function processUserBatch(users) {
  const batchResults = await Promise.allSettled(users.map(validateUser));

  // Collect valid users who passed all validations
  const validUsers = batchResults
    .filter(r => r.status === 'fulfilled' && r.value.isValid)
    .map(r => r.value.user);

  // Collect users with failed validations or unexpected errors
  const failedValidations = batchResults
    .filter(r => r.status === 'fulfilled' && !r.value.isValid)
    .map(r => ({
      user: r.value.user,
      errors: r.value.unexpectedError
        ? { unexpectedError: r.value.unexpectedError }
        : extractErrors(r.value.validationResults)
    }));

  return { validUsers, failedValidations };
}

This code demonstrates how Promise.allSettled() can handle complex validations, where multiple checks need to be performed for each user, and we want to collect all validation failures rather than stopping at the first error.

Good Practices and Common Pitfalls

When working with Promise.allSettled(), there are several important practices to keep in mind.

First, remember that the method always resolves – it never rejects. This means you don’t need to add a catch handler, but you do need to carefully check the status of each result.

One common mistake is assuming all promises were fulfilled:

// ❌ Incorrect usage
Promise.allSettled(promises).then(results => {
  results.forEach(result => {
    console.log(result.value); // May be undefined for rejected promises
  });
});

// ✅ Correct usage
Promise.allSettled(promises).then(results => {
  results.forEach(result => {
    if (result.status === 'fulfilled') {
      console.log(result.value);
    } else {
      console.log('Failed:', result.reason);
    }
  });
});

Another consideration is performance. While Promise.allSettled() is great for handling multiple independent operations, it waits for all promises to settle before resolving. This can be particularly problematic if one operation takes significantly longer than the others, for example an API is not responding and will eventually time out. So always consider if Promise.allSettled() really is the best choice for your use case.

To mitigate performance issues, for large arrays of promises consider processing them in smaller batches:

async function processBatches(items, batchSize = 5) {
  const results = [];

  for (let i = 0; i < items.length; i += batchSize) {
    const batch = items.slice(i, i + batchSize);
    const batchPromises = batch.map(item => processItem(item));
    const batchResults = await Promise.allSettled(batchPromises);
    results.push(...batchResults);
  }

  return results;
}

When to Use Promise.allSettled()

Promise.allSettled() is particularly useful in scenarios where:

  • You need to perform multiple independent operations and want to know the outcome of each one.
  • Partial success is acceptable and you want to handle failures gracefully.
  • You’re building robust applications that need to continue functioning even when some operations fail.
  • You need to collect and report all successes and failures rather than stopping at the first error.

However, there are cases where other promise combinator methods might be more appropriate. Use Promise.all() when all promises must succeed for the operation to be meaningful, Promise.race() when you only need the first result, or Promise.any() when you need the first successful result.

Key Takeaways

The Promise.allSettled() method allows you to handle multiple promises without failing everything if one rejects.

Instead of stopping early like Promise.all(), it waits for all promises to settle and provides their results, making it useful when you need to process both successes and failures.

Use Promise.allSettled() when you want to handle partial failures without affecting the entire operation. It’s a good fit for scenarios like fetching data from multiple sources, processing batches of tasks, or handling user inputs where some may fail.


Promises are a fundamental part of modern asynchronous JavaScript, but they are just one piece of the puzzle. To fully grasp asynchronous programming, it’s important to see how Promises fit within the bigger picture – how they interact with async/await, how JavaScript schedules tasks, and how Promise combinators like Promise.all and Promise.race help manage multiple asynchronous operations. Explore these concepts in depth in our Mastering Asynchronous JavaScript guide.

Article by:

With 20 years of experience in development, I’m passionate about JavaScript, clean code, and software architecture. I share clear and practical insights for developers. Learn more about me or follow me on LinkedIn and X.