Skip to the solution
MediumFrontend6 min read

What does Promise.withResolvers() solve and how does it replace the deferred anti-pattern?

215 views

The problem

Question presented to candidate: "Before Promise.withResolvers existed, if you needed to resolve a Promise from OUTSIDE its executor function β€” say, from an event listener registered elsewhere β€” how would you have done it? What does Promise.withResolvers actually give you that's different?"

What a strong answer should cover:

  • πŸ“Œ Interview term: Promise.withResolvers() β€” a static ES2024 method returning a real object { promise, resolve, reject } in ONE call β€” verified directly: promise is a genuine Promise instance, and resolve/reject are real, working functions that settle it from anywhere.
  • πŸ“Œ Interview term: the real, direct answer to the prompt's historical question β€” the classic pre-withResolvers "deferred" pattern: manually declaring let resolveFn, rejectFn; OUTSIDE a new Promise((res, rej) => { resolveFn = res; rejectFn = rej; }) executor, capturing them via closure β€” verified directly to have the IDENTICAL real shape/capability as Promise.withResolvers(), just requiring several manual lines instead of one call.
  • πŸ“Œ Interview term: the real, practical use case β€” verified directly: resolving a Promise from inside an external, event-callback-style function (simulating an event listener registered elsewhere, entirely outside any executor) β€” exactly the scenario the prompt describes, confirmed working correctly.
  • A precise answer names that Promise.withResolvers() does not add any NEW capability beyond the deferred pattern β€” both genuinely expose resolve/reject outside the executor β€” its real value is ergonomic: one direct call versus manually declaring, capturing, and correctly typing several separate variables.
  • A precise answer names a genuinely common real use case beyond events: bridging a callback-based API (or any external system that "calls back" later) into a single Promise, without needing to wrap the ENTIRE calling code inside a new Promise executor.

Clarifying questions expected:

  • None β€” this is a definitional/historical-technical question; directly naming and reproducing the deferred anti-pattern it replaces is the strong signal.

Code / implementation expected: Yes β€” real, side-by-side proof of the classic manual deferred pattern next to Promise.withResolvers()'s identical shape, plus the real external-event use case, is the clearest demonstration.

  • promises
  • es2024
  • 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

6 min read Β· 8 sections

Run the code

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

JavaScriptReal, side-by-side proof: Promise.withResolvers() has the identical shape as the classic manual deferred pattern, plus a real external-callback use case

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 108 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 nextMedium

What is BigInt?

Continue