Suggest an editImprove this articleRefine the answer for “Promise.withResolvers()”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`Promise.withResolvers()` is a static method that creates a new promise and immediately returns an object `{ promise, resolve, reject }`. It is the official way to get hold of external `resolve` and `reject` without writing `new Promise((resolve, reject) => { ... })` and without leaking those functions out of the executor into outer variables. No executor runs here at all: you get the promise together with its remote control.** ```javascript const { promise, resolve, reject } = Promise.withResolvers(); setTimeout(() => resolve('Success'), 1000); promise.then(console.log).catch(console.error); ``` **Key point:** it is the standard replacement for the deferred pattern, cleaner and more type-safe than assigning `resolve` to an outer variable by hand.Shown above the full answer for quick recall.Answer (EN)Image**`Promise.withResolvers()` creates a new promise and hands it back together with the `resolve` and `reject` functions that control it from the outside.** It is the standard, safe replacement for the old trick of pulling `resolve` and `reject` out of the `new Promise` constructor. ## Theory ### TL;DR - Calling `Promise.withResolvers()` returns an object `{ promise, resolve, reject }`. - No executor runs at all: there is no `(resolve, reject) => {}` callback, just a ready-made object. - It is the official form of the deferred pattern: the promise is controlled from anywhere in the code after it was created. - It replaces the old trick with two outer variables, which was unobvious and typed poorly. - Support: Chrome 120+, Node.js 20.11+, Deno 1.41+, Safari 17.4+. ### Quick example ```javascript const { promise, resolve, reject } = Promise.withResolvers(); setTimeout(() => resolve('Success'), 1000); promise.then(console.log).catch(console.error); ``` A second later the console shows: ```javascript Success ``` Exactly what previously had to be done by hand through `new Promise`. ### What the method returns The method creates a **new promise** and immediately returns an object with **three properties**: | Property | Type | Description | | --- | --- | --- | | `promise` | `Promise` | The promise itself, which you can return or await | | `resolve` | `Function` | Moves the promise into the `fulfilled` state | | `reject` | `Function` | Moves the promise into the `rejected` state | In other words, it is the official way to obtain external `resolve` and `reject` without `new Promise((resolve, reject) => { ... })`. The signature as TypeScript sees it: ```javascript Promise.withResolvers<T>() => { promise: Promise<T>, resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void } ``` That makes the code safer: the IDE knows the type of `promise` and the argument type of its `resolve`. ### How it was done before Before `Promise.withResolvers()` appeared, people wrote this: ```javascript let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); ``` It looked unobvious (especially in TypeScript, where the variables stayed `undefined` until assignment) and was potentially dangerous: `resolve` and `reject` could be overwritten by accident. Now the same thing is done safely and declaratively: ```javascript const { promise, resolve, reject } = Promise.withResolvers(); ``` A simple analogy: `Promise.withResolvers()` is a promise that ships with its remote control included. You used to have to prise the `resolve` and `reject` buttons out by hand, now they come out of the box. ### Practical scenarios **Waiting for an event.** The classic case where the promise must be settled from the outside: ```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('The button was clicked'); ``` **Deferred tasks.** The promise is created in one place and settled somewhere else entirely: ```javascript const deferred = Promise.withResolvers(); // somewhere in the code setTimeout(() => deferred.resolve('Done'), 2000); // and somewhere else deferred.promise.then(console.log); ``` After 2 seconds the console prints `Done`. **Combining with AbortController.** An external `reject` is convenient to hook onto a cancellation signal: ```javascript const controller = new AbortController(); const { promise, resolve, reject } = Promise.withResolvers(); controller.signal.addEventListener('abort', () => reject(new Error('Aborted'))); setTimeout(() => resolve('Success'), 2000); // somewhere later controller.abort(); promise.catch(console.error); ``` It prints: ```javascript Error: Aborted ``` ### Behaviour and support | Trait | Description | | --- | --- | | Creates a new `Promise` | with no need to write the constructor by hand | | Convenient for the deferred pattern | when the result becomes known later | | Runs no executor | no `(resolve, reject)` arguments, just an object | | Allows external control | the promise can be driven after it was created | Summary: | Item | Value | | --- | --- | | `Promise.withResolvers()` | Creates a promise and returns `resolve` and `reject` | | **Returns** | `{ promise, resolve, reject }` | | **Advantages** | Cleaner, safer and more type-safe than `new Promise(...)` | | **Used for** | Deferred tasks, events, external control of a promise | | **Support** | Chrome 120+, Node.js 20.11+, Deno 1.41+, Safari 17.4+ | ### Common mistakes - **Forgetting `catch` on the `promise`.** If something calls `reject` and there is no handler, you get an unhandled rejection. That is especially easy to miss when `reject` lives in another module. - **Creating a promise and never settling it.** If neither `resolve` nor `reject` is ever called, an `await` on it hangs forever, and closures and subscriptions leak along with it. - **Thinking a second `resolve` changes anything.** A promise settles once: the second `resolve` or `reject` call is silently ignored. - **Using it where plain `new Promise` would do.** If all the asynchronous logic fits inside the executor, external `resolve` and `reject` only smear the control flow across the code. - **Counting on the method in older runtimes.** It is a fairly recent addition: older browsers or Node.js versions need a polyfill or the familiar `new Promise`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.