Blog/NotesConcept

Promise.any Polyfill in JavaScript - Detailed Explanation

A step-by-step detailed explanation of Promise.any polyfill in JavaScript to understand the internal implementation to handle race conditions among promises to result in a single resolved promise.

beginner

Frontendgeek

Last Updated Sep 18, 2025


Jump to the topic

  1. How does Promise.any work in javascript?
  2. Promise.any Polyfill in Javascript - Detailed Explanation

How does Promise.any work in JavaScript?

Promise.any() takes multiple promises and returned the first one that resolved. If all promises reject, it returns an AggregateError object containing all the error messages for all the rejected promises. Promise.any static method is quite useful in the cases where in the application we are just looking for the first success response and sequence doesn't matter in this case.

Real life Use Cases:

If your app serves images from multiple CDNs, you want the fastest CDN to load the image first.

In WebRTC-based applications, connect to the fastest signaling server for real-time communication.

Examples

1. When any one of the promise got fulfilled

const p1 = new Promise((resolve, reject) => setTimeout(reject, 1000, "Error from p1"));
const p2 = new Promise((resolve, reject) => setTimeout(resolve, 2000, "Success from p2"));
const p3 = new Promise((resolve, reject) => setTimeout(resolve, 3000, "Success from p3"));

Promise.any([p1, p2, p3])
  .then((result) => console.log("First fulfilled promise:", result))
  .catch((error) => console.error("All promises rejected:", error));

Output

// After 2 seconds
First fulfilled: Success from p2

Explanation:

  • p1 rejects after 1s.

  • p2 resolves after 2s, this is the first fulfilled promise that's why Promise.any() returns its value.

  • p3 resolves after 3s, but since p2 promise already fulfilled, p3 is ignored.

2. When all the promises got rejected

When all the promises reject, Promise.any() throws an AggregateErrorAggregateError is an object which contains all the rejected responses as part of an errors array.

const p1 = Promise.reject("Error from p1");
const p2 = Promise.reject("Error from p2");
const p3 = Promise.reject("Error from p3");

Promise.any([p1, p2, p3])
  .then((result) => console.log("First fulfilled:", result))
  .catch((error) => {
       console.log(error instanceof AggregateError); // true
       console.error("All promises rejected:", error.errors);
  });

output:

true 
All promises rejected: [ 'Error from p1', 'Error from p2', 'Error from p3' ]

Expected Functionality for Promise.any Implementation

Here are the Promise.any expected functionalities that needs to be take care while implementing polyfill for Promise.any() .

āŒ - Not executed, āœ… - Executed

Case1: Promise.any should return the first resolved value

Promise.any([
  Promise.reject("Error A"),
  Promise.resolve("Success B"), // First resolved promise
  Promise.resolve("Success C"),
])
  .then(result => console.log("āœ… First resolved:", result))
  .catch(error => console.error("āŒ Unexpected error:", error));

// Output
āœ… First resolved: Success B

Returns the first resolved promise, others got ignored.

Promise.any([
  new Promise(res => setTimeout(res, 500, "Success A")), // resolved first
  new Promise((res, rej) => setTimeout(rej, 300, "Error B")),
  new Promise(res => setTimeout(res, 600, "Success C")), // resolved second
])
  .then(result => console.log("āœ… First resolved:", result))
  .catch(error => console.error("āŒ Unexpected error:", error));

// Output
āœ… First resolved: Success A

 

Case2: When all promise rejected or passed iterable is empty, Promise.any should throw AggregateError

Promise.any([
  Promise.reject("Error A"),
  Promise.reject("Error B"),
])
  .then(result => console.log("āŒ Success:", result))
  .catch(error => console.log("āœ… AggregateError caught:", error.errors));

// Output
āœ… AggregateError caught: ["Error A", "Error B"]

Empty iterable

Promise.any([])
  .then(result => console.log("āŒ Unexpected success:", result))
  .catch(error => console.log("āœ… AggregateError caught:", error.errors));

// Output
āœ… AggregateError caught: []

 

Case3: In case of already resolved promise it directly returns that first resolved promise

Promise.any([
  Promise.resolve("Immediate Success1"),
  Promise.resolve("Immediate Success2"),
  Promise.reject("Immediate Reject")
])
  .then(result => console.log("āœ… Immediate resolved:", result))
  .catch(error => console.error("āŒ Unexpected error:", error));

// Output
āœ… Immediate resolved: Immediate Success1

 

Case4: In case of non-promise iterable, Promise.any() returns the non-promise values if that is the first one to process, before any resolved promise

//--------Example 1--------------
Promise.any([
  Promise.reject("Error"),
  Promise.resolve("world"),
  "Non-promise"
])
  .then(result => console.log("āœ… First resolved:", result))
  .catch(error => console.error("āŒ Unexpected error:", error));

//Output
āœ… First resolved: world

//--------Example 2--------------
Promise.any([
  "Non-promise",
  Promise.reject("Error"),
  Promise.resolve("world")
])
  .then(result => console.log("āœ… First resolved:", result))
  .catch(error => console.error("āŒ Unexpected error:", error));

//Output
āœ… First resolved: Non-promise

Promise.any Polyfill in Javascript - Detailed Explanation

Here are the 3 steps with explanation, those are required to implement the polyfill of Promise.any()

Step 1: Handle empty iterable input

If Promise.any([]) is called, it immediately rejects with AggregateError.

if (!Array.isArray(promises) || promises.length === 0) {
  reject(new AggregateError([], "All promises were rejected"));
  return;
}

Step 2: Loop over all the input promises

Maintain an array of rejections to track the all rejection messages those will pass to AggregatorError, along with the length of the input promises.

let rejections = [];
let pending = promises.length;

promises.forEach((promise, index) => {
     // Loop over
})

Step 3: Pass each promise to Promise.resolve()

In the loop pass each promise to Promise.resolve(), and track the fulfilled and rejected promises. In case of resolved promise, first resolved promise will be returned, other wise in case of rejected promises push the rejected error message for AggregatorError and keep track of the length of the promises. If all the promises found as rejected then an AggregatorError object should be returned with all the rejected error messages with rejections array.

Promise.resolve(promise)
  .then(resolve)
  .catch((err) => {
    rejections[index] = err;
    pending--;

    if (pending === 0) {
      reject(new AggregateError(rejections, "All promises were rejected"));
    }
  });

Full Promise.any Polyfill Implementation Code

Promise.customAny = function (promises) {
    return new Promise((resolve, reject) => {
      // Step 1
      if (!Array.isArray(promises) || promises.length === 0) {
        reject(new AggregateError([], "All promises were rejected"));
        return;
      }
      
      // Step 2
      let rejections = [];
      let pending = promises.length;

      promises.forEach((promise, index) => {
        // Step 3
        Promise.resolve(promise)
          .then(resolve) // āœ… First fulfilled promise resolves
          .catch((err) => {
            rejections[index] = err;
            pending--;

            // āŒ If all promises are rejected, return AggregateError
            if (pending === 0) {
              reject(new AggregateError(rejections, "All promises were rejected"));
            }
          });
      });
    });
  };

// Test
Promise.customAny([
  new Promise(res => setTimeout(res, 500, "Success A")), // resolved first
  new Promise((res, rej) => setTimeout(rej, 300, "Error B")),
  new Promise(res => setTimeout(res, 600, "Success C")), // resolved second
])
  .then(result => console.log("āœ… First resolved:", result))
  .catch(error => console.error("āŒ Unexpected error:", error));

// Output
āœ… First resolved: Success A

Learn Next

  1. Notes to Master Promise Methods in JavaScript: all(), allSettled(), race() and any()
  2. Promise Polyfill in JavaScript - Step by Step Explanation
  3. Promise.all Polyfill in JavaScript - Detailed Explanation [For Interviews]
  4. Promise.allSettled Polyfill in JavaScript - Step by Step Explanation
  5. Promise.race Polyfill in Javascript - Detailed Explanation
  6. Promise.any polyfill in JavaScript explained

Love this Blog? Share it Now!

Help others discover this resource

About the Author

Frontendgeek

One of the leading, Frontend platform to help frontend devs to prepare and ace all rounds of frontend interview with ease.

Learn Next

Featured

20 Most Asked Custom Hooks in React for Interviews

Top 10 React Performance Optimization Techniques25 Top JavaScript Interview Questions for BeginnersHow to create custom useInfiniteScroll Hook in ReactImplement useThrottle Custom Hook In React

Comments

Be the first to share your thoughts!

Guest User

Please login to comment

0 characters


No comments yet.

Start the conversation!

About the Author

Frontendgeek

One of the leading, Frontend platform to help frontend devs to prepare and ace all rounds of frontend interview with ease.

Share your expertise

Publish a blog or quick notes on topics you know well — your write-up could be the answer someone needs before their next frontend interview.

Build your portfolio

Help the community

Sharpen your skills

Earn goodies

Other Related Blogs

clearTimeout polyfill in JavaScript - Detailed Explanation

Anuj Sharma

Last Updated Jun 15, 2026

Understand the implementation of the clearTimeout polyfill in JavaScript with a detailed explanation of each and every step.

Promise.race Polyfill in Javascript - Detailed Explanation

Anuj Sharma

Last Updated Jun 15, 2026

Detailed step-by-step explanation of Promise.race polyfill in javascript to understand its internal working and handling of race conditions among promises.

setInterval polyfill in JavaScript - Detailed Explanation

Anuj Sharma

Last Updated Jun 15, 2026

Understand the implementation of the setInterval polyfill in JavaScript with a detailed explanation of each and every step.

setTimeout Polyfill in JavaScript - Detailed Explanation

Anuj Sharma

Last Updated Jun 15, 2026

Explore the implementation of setTimeout in JavaScript with a detailed explanation for every step. Understand all scenarios expected to implement the setTimeout polyfill.

Promise Polyfill in JavaScript - Step by Step Explanation

Anuj Sharma

Last Updated Jun 15, 2026

An Interview-focused explanation of Promise Polyfill in JavaScript which helps to understand both Functional and ES6 custom promise implementation.

Promise.all Polyfill in JavaScript - Detailed Explanation [For Interviews]

Anuj Sharma

Last Updated Jun 5, 2026

Deep dive into promise.all polyfill in javascript will help to understand the working of parallel promise calls using Promise.all and its implementation to handle parallel async API calls.

Polyfill for Async Await in JavaScript - Step by Step Explanation

Anuj Sharma

Last Updated Feb 21, 2026

Understand polyfill for Async Await in JavaScript with a step-by-step explanation. This helps in understanding the internal functioning of Async Await in JavaScript.

Promise.allSettled Polyfill in JavaScript - Step by Step Explanation

Frontendgeek

Last Updated Sep 18, 2025

Deep dive into Promise.allSettled Polyfill in JavaScript, which helps to understand the internal implementation of Promise.allSettled method to handle parallel calls with failure cases.

Stay Updated

Subscribe to FrontendGeek Hub for frontend interview preparation, interview experiences, curated resources and roadmaps.

FrontendGeek
FrontendGeek

All in One Preparation Hub to Ace Frontend Interviews. Master JavaScript, React, System Design, and more with curated resources.

Consider Supporting this Free Platform

Buy Me a Coffee

Product

HomeFrontend InterviewFrontend JobsQuestionsNewInterview ExperienceBlogsToolsLeaderboardFrontendGeek Chrome extensionGet the extension on the Chrome Web Store →

Ā© 2026 FrontendGeek. All rights reserved