import {getTimer, TIMER_WAIT} from '../internal/function/timer'; import type {RequiredKeys} from '../models'; import {getPromiseOptions} from './helpers'; import {settlePromise} from './misc'; import { PROMISE_ABORT_OPTIONS, PROMISE_ABORT_EVENT, PROMISE_MESSAGE_EXPECTATION_TIMED, PromiseTimeoutError, type PromiseOptions, } from './models'; // #region Functions export async function getTimedPromise( promise: Promise, time: number, signal?: AbortSignal, ): Promise { function abort(): void { timer.cancel(); rejector(signal!.reason); } signal?.addEventListener(PROMISE_ABORT_EVENT, abort, PROMISE_ABORT_OPTIONS); const timer = getTimer( TIMER_WAIT, () => { settlePromise(abort, rejector, new PromiseTimeoutError(), signal); }, time, ); let rejector: (reason: unknown) => void; return Promise.race([ promise, new Promise((_, reject) => { rejector = reject; timer(); }), ]).then(value => { timer.cancel(); rejector(undefined); signal?.removeEventListener(PROMISE_ABORT_EVENT, abort); return value; }); } /** * Create a _Promise_ that should be settled within a certain amount of time * * @param promise _Promise_ to settle * @param options Timed options * @returns Timed _Promise_ */ export async function timed( promise: Promise, options: RequiredKeys, ): Promise; /** * Create a _Promise_ that should be settled within a certain amount of time * * @param promise _Promise_ to settle * @param time How long to wait for _(in milliseconds; defaults to `0`)_ * @returns Timed _Promise_ */ export async function timed(promise: Promise, time: number): Promise; export async function timed(promise: Promise, options: unknown): Promise { if (!(promise instanceof Promise)) { return Promise.reject(new TypeError(PROMISE_MESSAGE_EXPECTATION_TIMED)); } const {signal, time} = getPromiseOptions(options); if (signal?.aborted ?? false) { return Promise.reject(signal!.reason); } return time > 0 ? getTimedPromise(promise, time, signal) : promise; } // #endregion