UNPKG

@oxog/delay

Version:

A comprehensive, zero-dependency delay/timeout utility library with advanced timing features

109 lines 4.19 kB
import { DelayError, DelayErrorCode } from '../types/index.js'; import { validateDelay } from '../utils/validation.js'; import { getHighResolutionTime } from '../utils/time.js'; export function createBasicDelay(ms, options = {}) { validateDelay(ms); return new Promise((resolve, reject) => { const { signal, onProgress, progressInterval = 100 } = options; // Check if already aborted if (signal?.aborted) { reject(new DelayError('Delay was aborted', DelayErrorCode.CANCELLED)); return; } // Handle immediate resolve for zero delay (but still check for cancellation) if (ms === 0) { // Use setTimeout to allow for cancellation even on zero delay const timeoutId = setTimeout(() => { if (!signal?.aborted) { resolve(); } }, 0); signal?.addEventListener('abort', () => { clearTimeout(timeoutId); reject(new DelayError('Delay was cancelled', DelayErrorCode.CANCELLED)); }); return; } const startTime = getHighResolutionTime(); let timeoutId; let progressIntervalId; let isResolved = false; const cleanup = () => { if (typeof timeoutId === 'number') { clearTimeout(timeoutId); } else { clearTimeout(timeoutId); } if (progressIntervalId !== undefined) { if (typeof progressIntervalId === 'number') { clearInterval(progressIntervalId); } else { clearInterval(progressIntervalId); } } }; const handleAbort = () => { if (!isResolved) { isResolved = true; cleanup(); reject(new DelayError('Delay was cancelled', DelayErrorCode.CANCELLED)); } }; const handleResolve = () => { if (!isResolved) { isResolved = true; cleanup(); signal?.removeEventListener('abort', handleAbort); resolve(); } }; // Set up abort handling signal?.addEventListener('abort', handleAbort); // Set up progress tracking if (onProgress && ms > progressInterval) { const updateProgress = () => { if (!isResolved) { const elapsed = getHighResolutionTime() - startTime; const clampedElapsed = Math.min(elapsed, ms); onProgress(clampedElapsed, ms); if (elapsed >= ms) { if (progressIntervalId !== undefined) { if (typeof progressIntervalId === 'number') { clearInterval(progressIntervalId); } else { clearInterval(progressIntervalId); } } } } }; progressIntervalId = setInterval(updateProgress, progressInterval); // Call immediately for initial progress updateProgress(); } // Set the main timeout timeoutId = setTimeout(handleResolve, ms); }); } export function createProgressiveDelay(ms, onProgress, progressInterval = 100) { return createBasicDelay(ms, { onProgress, progressInterval }); } export function msDelay(milliseconds, options) { return createBasicDelay(milliseconds, options); } export function secondsDelay(seconds, options) { return createBasicDelay(seconds * 1000, options); } export function minutesDelay(minutes, options) { return createBasicDelay(minutes * 60 * 1000, options); } export function hoursDelay(hours, options) { return createBasicDelay(hours * 60 * 60 * 1000, options); } export function daysDelay(days, options) { return createBasicDelay(days * 24 * 60 * 60 * 1000, options); } //# sourceMappingURL=delay.js.map