// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. // This module is vendored from std/async/deferred.ts and std/async/delay.ts // (with some modifications) // TODO(petamoriken): enable prefer-primordials for node polyfills // deno-lint-ignore-file prefer-primordials export interface Deferred extends Promise { readonly state: "pending" | "fulfilled" | "rejected"; resolve(value?: T | PromiseLike): void; // deno-lint-ignore no-explicit-any reject(reason?: any): void; } /** Creates a Promise with the `reject` and `resolve` functions */ export function deferred(): Deferred { let methods; let state = "pending"; const promise = new Promise((resolve, reject) => { methods = { async resolve(value: T | PromiseLike) { await value; state = "fulfilled"; resolve(value); }, // deno-lint-ignore no-explicit-any reject(reason?: any) { state = "rejected"; reject(reason); }, }; }); Object.defineProperty(promise, "state", { get: () => state }); return Object.assign(promise, methods) as Deferred; } /** Resolve a Promise after a given amount of milliseconds. */ export function delay( ms: number, options: { signal?: AbortSignal } = {}, ): Promise { const { signal } = options; if (signal?.aborted) { return Promise.reject(new DOMException("Delay was aborted.", "AbortError")); } return new Promise((resolve, reject) => { const abort = () => { clearTimeout(i); reject(new DOMException("Delay was aborted.", "AbortError")); }; const done = () => { signal?.removeEventListener("abort", abort); resolve(); }; const i = setTimeout(done, ms); signal?.addEventListener("abort", abort, { once: true }); }); }