/** * A collection of utility functions for working with Promises. */ export class Promises { /** * Creates a new Promise and returns it in an object, along with its resolve and reject functions. * @returns An object with the properties `promise`, `resolve`, and `reject`. * * ```ts * const { promise, resolve, reject } = Promise.withResolvers(); * ``` * * - Chrome 119, Safari 17.4 * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers */ static withResolvers(): PromiseWithResolvers { const P = Promise as unknown as { new ( executor: (resolve: (value: T | PromiseLike) => void, reject: (reason?: any) => void) => void, ): Promise; withResolvers?(): PromiseWithResolvers; }; if (P.withResolvers) { return P.withResolvers(); } let resolve: (value: T | PromiseLike) => void; let reject: (reason?: any) => void; const promise = new P((res, rej) => { resolve = res; reject = rej; }); return { promise, resolve: resolve!, reject: reject! }; } /** * Creates a new Promise and returns it in an object, along with its resolve and reject functions. * @param ms The number of milliseconds to wait before rejecting the promise. */ static sleep(ms: number): Promise { return new Promise((resolve) => setTimeout(resolve, ms)); } /** * Returns `true` if the given value is a Promise. * @param v The value to check. */ static isPromise(v: any): v is PromiseLike { return v && (v instanceof Promise || typeof v.then === 'function'); } /** * Returns a Promise that resolves when the given signal is aborted. */ static aborted(signal: AbortSignal): Promise { // https://nodejs.org/api/util.html#utilabortedsignal-resource return new Promise((_, reject) => { signal.addEventListener('abort', () => reject(new DOMException('Aborted', 'AbortError'))); }); } } interface PromiseWithResolvers { promise: Promise; resolve: (value: T | PromiseLike) => void; reject: (reason?: any) => void; }