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.

Promise static methodES2015
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

NameTypeRequiredDescription
valueanyyesAny 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
true
2. A value is wrapped
Promise.resolve(1) instanceof Promise
Returns
true
3. Each call is a new promise
Promise.resolve(1) === Promise.resolve(1)
Returns
false
4. 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
undefined
7. Still asynchronous
let x; Promise.resolve(1).then(v => { x = v; }); x
Returns
undefined at this point

Pitfalls

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.