Promise.resolve()
The bridge from a plain value into promise-land. Its pass-through behaviour makes it safe to call on something that may or may not be a promise, which is exactly why it exists.
Common call
Promise.resolve(maybePromise)
Returns
a promise — the SAME one if it already was
Replaces
new Promise(r => r(value))
Watch out
a thenable is adopted, so a stray then property matters
Promise.resolve(valuevalue — Any value. A promise is returned as-is. A thenable — any object with a then method — is ADOPTED, so its then is called to determine the outcome.type: any · required)
→ Promise
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| value | any | yes | Any value. A promise is returned as-is. A thenable — any object with a then method — is ADOPTED, so its then is called to determine the outcome. |
Return value
Promise — A Promise fulfilled with the value. If the value is ALREADY a promise, that same promise is returned — not a wrapper around it.
Common patterns
Normalise a maybe-promise
Safe whether or not the value is already one.
const p = Promise.resolve(maybeAsync());
Start a chain from a value
Gives you somewhere to hang then handlers.
Promise.resolve(seed).then(step1).then(step2);
An async function does it implicitly
Returning a value from async wraps it.
async function f() { return 1; } // Promise<1>
Examples
1. A promise passes through
const p = Promise.resolve(1);
Promise.resolve(p) === p
Returns
true2. A value is wrapped
Promise.resolve(1) instanceof Promise
Returns
true3. Each call is a new promise
Promise.resolve(1) === Promise.resolve(1)
Returns
false4. A thenable is adopted
await Promise.resolve({then: r => r("from thenable")})
Returns
'from thenable'5. A non-callable then is not
await Promise.resolve({then: 1, data: "x"})
Returns
{then: 1, data: "x"}6. Undefined is fine
await Promise.resolve()
Returns
undefined7. Still asynchronous
let x;
Promise.resolve(1).then(v => { x = v; });
x
Returns
undefined at this pointPitfalls
1. It is still asynchronous
An already-resolved promise does not run its callbacks synchronously — they are queued as microtasks. Code that resolves a value and reads the result on the next line gets undefined, which makes the promise look broken.
Too early
let x; Promise.resolve(1).then(v => { x = v; }); return x;
undefined
Await it
const x = await Promise.resolve(1); return x;
1
2. An object with a CALLABLE then is adopted
Thenable adoption is how promises from different libraries interoperate — and it means any object carrying a then METHOD is treated as a promise rather than as data. A non-callable then property is harmless, so parsed JSON with a numeric "then" field comes back untouched; the hazard is a data object that happens to have a then function on it.
Adopted, not returned
await Promise.resolve({then: r => r("adopted"), id: 1})
'adopted' — the object is gone
Wrap it to keep it
await Promise.resolve({value: {then: r => r("x"), id: 1}})
the wrapper, object intact
3. It does not deep-resolve the contents
Resolving an array of promises gives you a promise for an array OF PROMISES. Only Promise.all waits for the elements. This trips people converting from libraries that auto-resolve nested structures.
Promises inside
await Promise.resolve([Promise.resolve(1)])
[Promise]
Use all
await Promise.all([Promise.resolve(1)])
[1]
4. new Promise(r => r(v)) is the long way round
The constructor is for wrapping callback-based APIs. Using it to produce an already-resolved promise is noise, and the executor form invites the classic mistake of resolving inside a then instead of returning.
Verbose
new Promise(r => r(1))
works
Direct
Promise.resolve(1)
same thing
When to use
Use it
- Normalising a value that may or may not be a promise
- Starting a chain from a plain value
- Returning an already-known result from a promise-returning function
- Writing a test double for an async dependency
Reach for something else
- Wrapping a callback API → the Promise constructor
- You need external resolve and reject → Promise.withResolvers
- The value contains promises you want resolved → Promise.all
- Inside an async function → just return the value
Notes
Complexity
O(1)
Return
A Promise — the same object when the input already was one
CPython impl
V8: Builtins-promise-resolve
Memory
No allocation when the input is already a native promise
Thread-safe
Single-threaded
FAQ
Because everything about Promise.resolve that can be observed WITHOUT waiting is a constant — instanceof is always true, and the pass-through identity is always true. A demo would be a fixed answer pretending to be a computation. The examples above were run in a real runtime, including the ones that need awaiting.
History
ES2015
Promise.resolve added with the constructor; thenable adoption inherited from Promises/A+.
ES2017
async functions made implicit wrapping the common case.