-
-
Save lmammino/ef121da874a80d657379a1cd64bf8166 to your computer and use it in GitHub Desktop.
| if (typeof Promise.withResolvers === 'undefined') { | |
| Promise.withResolvers = function () { | |
| let resolve, reject | |
| const promise = new Promise((res, rej) => { | |
| resolve = res | |
| reject = rej | |
| }) | |
| return { promise, resolve, reject } | |
| } | |
| } | |
| // Usage: | |
| // const { promise, resolve, reject } = Promise.withResolvers() | |
| // console.log(promise, resolve, reject) // Promise { <pending> } [Function (anonymous)] [Function (anonymous)] | |
| // ... Do something async and then call resolve or reject! |
@lmammino this is not working:
Object.assign(Promise, {
withResolvers: () => {
let resolve;
let reject;
const promise = new Promise((resolve, reject) => {
resolve = resolve;
reject = reject;
});
return {
promise,
resolve,
reject
};
}});
const a = Promise.withResolvers()
a.promise.then(() => console.log('resolved'))
a.resolve();With this error:
VM717:20 Uncaught TypeError: a.resolve is not a function
at <anonymous>:20:3But I see that it is because of the name that I am reassigning the variable inside the function, not the one outside. It's totally my fault. Sorry about that.
A TypeScript version:
if (typeof Promise.withResolvers === "undefined") {
Promise.withResolvers = <T>() => {
let resolve: (value: T | PromiseLike<T>) => void;
let reject: (reason?: unknown) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve: resolve!, reject: reject! };
};
}@Stadly you can put the ! on the declaration, rather than on the return object.
if (typeof Promise.withResolvers === "undefined") {
Promise.withResolvers = <T>() => {
let resolve!: (value: T | PromiseLike<T>) => void;
let reject!: (reason?: unknown) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
};
}Thanks, @WORMSS! I was not aware :)
@lmammino this is not working:
Object.assign(Promise, { withResolvers: () => { let resolve; let reject; const promise = new Promise((resolve, reject) => { resolve = resolve; reject = reject; }); return { promise, resolve, reject }; }}); const a = Promise.withResolvers() a.promise.then(() => console.log('resolved')) a.resolve();With this error:
VM717:20 Uncaught TypeError: a.resolve is not a function at <anonymous>:20:3But I see that it is because of the name that I am reassigning the variable inside the function, not the one outside. It's totally my fault. Sorry about that.
bruh 🙈
For anyone that wants a ts version.
looked at bun https://bun.com/reference/globals/PromiseConstructor/withResolvers
something that stood out was that in bun the resolve prop is of type (value?: T | PromiseLike<T>) => void;
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (Promise.withResolvers === undefined) {
function __withResolvers<T, E = unknown>(): PromiseWithResolvers<T, E> {
let resolve: PromiseWithResolvers<T,E>["resolve"];
let reject: PromiseWithResolvers<T, E>["reject"];
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve: resolve!, reject: reject! };
}
Object.defineProperty(Promise, "withResolvers", {
value: __withResolvers,
writable: false,
configurable: false,
enumerable: false
});
}
declare global {
export type PromiseWithResolvers<T, E = unknown> = {
promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: E) => void;
};
interface PromiseConstructor {
/**
* Create a deferred promise, with exposed resolve and reject methods
* which can be called separately.
* This is useful when you want to return a Promise
* and have code outside the Promise resolve or reject it.
*/
withResolvers<T>(): PromiseWithResolvers<T>;
/**
* Creates a new Promise and returns it in an object, along with its resolve and reject functions.
*
* @returns {PromiseWithResolvers<T>} An object with the properties promise, resolve, and reject.
*/
withResolvers<T, E = unknown>(): {
promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: E) => void;
};
}
}
export {};
I just tested the snippet above with Node 20 and, as far as I can tell, it behaves as expected.
I hope the issue you describe is not runtime-dependent, because that would mean that the specific runtime is not spec-compliant.
Do you have an example I can try to run that illustrates the problem?