export type PollOptions = { intervalMs: number immediate?: boolean shouldStop?: (value: T) => boolean signal?: AbortSignal } function sleep(ms: number, signal?: AbortSignal) { if (ms <= 0) return Promise.resolve() return new Promise((resolve, reject) => { const timer = window.setTimeout(() => { signal?.removeEventListener('abort', onAbort) resolve() }, ms) function onAbort() { window.clearTimeout(timer) reject(new DOMException('Aborted', 'AbortError')) } if (signal) { if (signal.aborted) return onAbort() signal.addEventListener('abort', onAbort, { once: true }) } }) } export async function poll(fn: () => Promise, options: PollOptions) { const { intervalMs, immediate = true, shouldStop, signal } = options if (!immediate) await sleep(intervalMs, signal) while (true) { if (signal?.aborted) throw new DOMException('Aborted', 'AbortError') const value = await fn() if (shouldStop?.(value)) return value await sleep(intervalMs, signal) } }