Skip to main content

What does Promise.withResolvers() do?

What Promise.withResolvers() does

The method:

javascript
const { promise, resolve, reject } = Promise.withResolvers();

creates a new promise and immediately returns an object that has three properties:

PropertyTypeDescription
promisePromiseThe promise itself, which can be returned or awaited
resolveFunctionMoves the promise to the fulfilled state
rejectFunctionMoves the promise to the rejected state

In other words, this is the official way to get external resolve/reject, without needing to write new Promise((resolve, reject) => { ... }).


Example

javascript
const { promise, resolve, reject } = Promise.withResolvers(); setTimeout(() => resolve('Success!'), 1000); promise.then(console.log).catch(console.error);

After a second:

javascript
Success!

Everything that previously had to be done "manually" via new Promise.


The same thing "the old way"

Before Promise.withResolvers() existed, this was written like this:

javascript
let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; });

This looked non-obvious (especially for TypeScript) and was potentially unsafe - resolve and reject could be overwritten.

Now it can be done safely and declaratively:

javascript
const { promise, resolve, reject } = Promise.withResolvers();

Example 2 - using it for "external control"

This is handy when you need to control the completion of a promise from outside, for example:

javascript
function waitForEvent(emitter, event) { const { promise, resolve } = Promise.withResolvers(); emitter.once(event, resolve); return promise; }

Now you can write:

javascript
await waitForEvent(button, 'click'); console.log('Button clicked!');

Example 3 - deferred tasks (Deferred)

You can create a deferred promise (the deferred pattern):

javascript
const deferred = Promise.withResolvers(); // somewhere in the code setTimeout(() => deferred.resolve('Done!'), 2000); // and elsewhere deferred.promise.then(console.log);

Output after 2 seconds:

javascript
Done!

Example 4 - combining with AbortController

javascript
const controller = new AbortController(); const { promise, resolve, reject } = Promise.withResolvers(); controller.signal.addEventListener('abort', () => reject(new Error('Cancelled'))); setTimeout(() => resolve('Successful!'), 2000); // somewhere later controller.abort(); promise.catch(console.error);

Outputs:

javascript
Error: Cancelled

The returned structure

javascript
Promise.withResolvers<T>() => { promise: Promise<T>, resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void }

In TypeScript this makes the code safer - the IDE knows the type of promise and the type of its resolve.


Features and behavior

FeatureDescription
Creates a new Promisewithout needing to manually write the constructor
Handy for "deferred" patternsfor example, when the result becomes known later
Does not invoke an executorno (resolve, reject) arguments - just an object
Allows external controlthe promise can be controlled after it is created

A simple analogy

Promise.withResolvers() is as if you created a promise with a remote control included.

Previously you had to manually pull out the "resolve/reject" buttons, now they come right out of the box.


SUMMARY

PropertyWhat it does
Promise.withResolvers()Creates a promise + returns resolve and reject
Returns{ promise, resolve, reject }
AdvantagesCleaner, safer, and more type-safe than new Promise(...)
Used forDeferred tasks, events, external control of a promise
SupportChrome 120+, Node.js 20.11+, Deno 1.41+, Safari - coming soon

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.