Skip to the solution
HardDSA7 min read

How do you implement a custom Promise.any polyfill?

541 views

The problem

Question presented to candidate: "Promise.any takes an array of promises and resolves as soon as ANY one of them fulfills β€” it only rejects if every single one of them fails, and in that case it rejects with a special AggregateError containing all the individual failure reasons. Implement a polyfill for it. What happens if a rejection genuinely arrives before a fulfillment does? And what should the order of the errors be inside the AggregateError?"

What a strong answer should cover:

  • The outer promise resolves the instant ANY item fulfills β€” a rejection arriving first, even much faster than the eventual winner, must not affect the outcome at all.
  • The outer promise only rejects once EVERY item has rejected; that is the opposite failure condition from Promise.all.
  • The rejection reason is a real AggregateError, a built-in Error subclass added specifically for this purpose, whose .errors property is an array of every individual rejection reason.
  • That .errors array should preserve INPUT order (which promise was originally where), not the order the rejections actually happened to arrive in β€” this is the exact same indexing discipline Promise.all's polyfill needs for its results array.
  • An empty input array is a genuine edge case: it must reject immediately with an AggregateError containing zero errors, since there is nothing that could possibly fulfill.
  • AggregateError's constructor signature is new AggregateError(errorsIterable, message) β€” the errors come first, the message second, the reverse of what some engineers expect from plain Error.

Clarifying questions expected:

  • "Should the polyfill construct a real AggregateError, or is a plain Error with an attached .errors array acceptable if the environment predates AggregateError?" β€” a real interview-worthy compatibility question, since AggregateError is a newer addition than Promise itself.
  • "Do all the rejection reasons need to be captured even after the first one arrives, or can we stop tracking once we know the outer promise cannot possibly succeed?" β€” clarifies whether early-exit optimizations are in scope.

Code / implementation expected: Yes β€” a full, runnable polyfill plus a real test proving a fulfillment wins over a faster rejection, and that AggregateError.errors preserves input order.

  • promises
  • polyfill
  • async

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

7 min read Β· 7 sections

Run the code

Edit the code and run it here. Each console line with an expected value becomes a test.

JavaScriptThe polyfill plus a real test proving a fulfillment wins over a faster rejection, and error-order preservation (run directly)

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 145 of 165 in JavaScript

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

How would you write a deep-clone function that correctly handles a self-referencing (circular) object without infinite recursion?

Continue