UNPKG

rvx

Version:

A signal based rendering library

38 lines (34 loc) 1.06 kB
import type { Falsy } from "../core/types.js"; export interface PollFn<T> { (abort: AbortSignal): T | Falsy | Promise<T | Falsy>; } export class PollTimeoutError extends Error {} /** * Repeatedly call a function until a truthy value is returned. * * + The function is called at most every event cycle. * + If a timeout occurs, a {@link PollTimeoutError} is thrown and the abort signal passed to the function is aborted with the same error. * * @param fn The function to run. * @param timeout An optional timeout. * @returns The first truthy value. */ export async function poll<T>(fn: PollFn<T>, timeout?: number): Promise<T> { const ac = new AbortController(); let timer: undefined | number | NodeJS.Timeout; if (timeout !== undefined) { timer = setTimeout(() => ac.abort(new PollTimeoutError()), timeout); } try { for (;;) { const value = await fn(ac.signal); if (value) { return value as T; } ac.signal.throwIfAborted(); await new Promise<void>(r => setTimeout(r, 0)); } } finally { clearTimeout(timer); } }