Promise.resolve
The Promise.resolve()
static method "resolves" a given value to a Promise. If the value is:
- A native promise, return that promise.
- A non-thenable, return a promise that is already fulfilled with that value.
- A thenable,
Promise.resolve()
will call thethen()
method and pass a pair of resolving functions as arguments. A promise that has the same state as the thenable is returned.
A "thenable" is an interface that implements the .then()
method, which is called with two callbacks: one for when the promise is fulfilled, one for when it's rejected. Promises are also thenables.
Implement the Promise.resolve()
function as promiseResolve
. You can ignore the case where this is referenced within the implemented function.
See also: Promise.resolve vs new Promise(resolve)
Example
Resolving a non-promise.
const p = promiseResolve(42);
await p; // 42
Resolving a Promise.
const original = new Promise((resolve) => resolve(42));
const cast = promiseResolve(original);
await cast; // 42
Resolving a thenable.
const resolvedThenable = promiseResolve({
then(resolve, reject) {
resolve(42);
},
});
await resolvedThenable; // 42
Solution
export default function promiseResolve(value) {
if (value instanceof Promise) {
return value;
}
if (typeof value.then === 'function') {
return new Promise(value.then.bind(value));
}
return new Promise((resolve) => resolve(value));
}
In fact, the resolve
function can also handle thenables. So we can simplify the code even further.
export default function promiseResolve(value) {
if (value instanceof Promise) return value;
return new Promise((res, rej) => res(value));
}
Explanation
There are three cases to handle within the static Promise.resolve function:
- If the value is a native Promise, return it directly without creating a new instance. We can check for this case using
value instanceof Promise
. - If the value is not a thenable, return a promise that's fulfilled with the value. We can use a Promise constructor that calls resolve with the value.
- If the value is a thenable, the
then()
method will be called. Thethen()
method has the same signature as a Promise constructor. The first two cases are straightforward. Let's talk a bit about the last case. Since the Promise constructor and then() has the same parameters, one might be tempted to pass value.then to a new Promise e.g.new Promise(value.then)
and call it a day. However, the then() will lose the value of this. Hence we need to pass in value.then.bind(value) instead.
Nested thenables and promises should also be flattened. This is already handled by the resolve callbacks of a Promise constructor, so we don't have to manually attempt to flatten.
Promise.reject
The
Promise.reject()
static method returns aPromise
object that is rejected with a given reason. UnlikePromise.resolve()
,Promise.reject()
always wraps reason in a newPromise
object, even whenreason
is already aPromise
.
Implement the Promise.reject()
function as promiseReject
. You can ignore the case where this is referenced within the implemented function.
Example
try {
await promiseReject('Mayday!');
} catch (err) {
console.log(err); // Mayday!
}
Solution
Promise.reject
returns a Promise that is rejected. It is essentially a shorthand for new Promise((resolve, reject) => reject(reason))
. The only thing we need to note is to wrap the reason
value in a new Promise
object even when reason is already a Promise
.
export default function promiseReject(reason) {
return new Promise((res, rej) => rej(reason));
}