UNPKG

ixfx

Version:

A framework for programming interactivity

185 lines (182 loc) 5.52 kB
import { I as Interval } from './IntervalType-B4PbUkjV.js'; import { H as HasCompletion } from './Types-Bw7JwVUD.js'; /** * Runs a function continuously, returned by {@link continuously} */ type Continuously = HasCompletion & { /** * Starts loop. If already running, does nothing */ start(): void; /** * (Re-)starts the loop. If an existing iteration has been * scheduled, this is cancelled and started again. * * This can be useful when adjusting the interval */ reset(): void; /** * How many milliseconds since loop was started after being stopped. */ get elapsedMs(): number; /** * If disposed, the continuously instance won't be re-startable */ get isDisposed(): boolean; /** * Stops loop. It can be restarted using .start() */ cancel(): void; /** * Sets the interval speed of loop. Change will take effect on next loop. For it to kick * in earlier, call .reset() after changing the value. */ set interval(interval: Interval); /** * Gets the current interval, ie. speed of loop. */ get interval(): Interval; }; type ContinuouslySyncCallback = ( /** * Number of times loop * Ticks is reset when loop exits. */ ticks?: number, /** * Elapsed milliseconds. * Reset when loop exits */ elapsedMs?: number) => boolean | void; type ContinuouslyAsyncCallback = ( /** * Number of times loop has run * Reset when loop exits. */ ticks?: number, /** * Elapsed milliseconds. * Reset when loop exits. */ elapsedMs?: number) => Promise<boolean | void>; type OnStartCalled = `continue` | `cancel` | `reset` | `dispose`; /** * Options for {@link continuously} */ type ContinuouslyOpts = Readonly<{ /** * Abort signal to exit loop */ signal: AbortSignal; /** * If _true_, callback runs before waiting period. * @defaultValue false */ fireBeforeWait: boolean; /** * Called whenever .start() is invoked. * If this function returns: * - `continue`: the loop starts if it hasn't started yet, or continues if already started * - `cancel`: loop stops, but can be re-started if .start() is called again * - `dispose`: loop stops and will throw an error if .start() is attempted to be called * - `reset`: loop resets (ie. existing scheduled task is cancelled) * */ onStartCalled: ( /** * Number of times loop has run * Reset when loop is exits. */ ticks?: number, /** * Elapsed milliseconds. * Reset when loop is exits. */ elapsedMs?: number) => OnStartCalled; }>; /** * Returns a {@link Continuously} that continually executes `callback` at `interval` rate. * * By default, first the sleep period happens and then the callback happens. * * Call `start` to begin/reset loop. The looping stops when `cancel` is called, or when `callback` returns _false_. * * @example * Animation loop * ```js * const draw = () => { * // Draw on canvas * } * * // Run draw() synchronised with monitor refresh rate via `window.requestAnimationFrame` * continuously(draw).start(); * ``` * * @example * With delay * ```js * const fn = () => { * // Runs after one minute * } * const c = continuously(fn, { mins: 1 } ); * c.start(); // Runs `fn` every minute * ``` * * @example * Control a 'continuously' * ```js * c.cancel(); // Stop the loop, cancelling any up-coming calls to `fn` * c.elapsedMs; // How many milliseconds have elapsed since start * c.ticks; // How many iterations of loop since start * c.interval; // Get/set speed of loop. Change kicks-in at next loop. * // Use .start() to reset to new interval immediately * ``` * * Asynchronous callback functions are supported too: * ```js * continuously(async () => { ..}); * ``` * * The `callback` function can receive a few arguments: * * ```js * continuously( (ticks, elapsedMs) => { * // ticks: how many times loop has run * // elapsedMs: how long since last loop * }).start(); * ``` * * If the callback explicitly returns _false_, the loop will be cancelled. * * ```js * continuously(ticks => { * // Stop after 100 iterations * if (ticks > 100) return false; * }).start(); * ``` * * You can intercept the logic for calls to `start()` with `onStartCalled`. It can determine * whether the `start()` proceeds, if the loop is cancelled, or the whole thing disposed, * so it can't run any longer. * * ```js * continuously(callback, intervalMs, { * onStartCalled:(ticks, elapsedMs) => { * // Cancel the loop after 1000ms has elapsed * if (elapsedMs > 1000) return `cancel`; * } * }).start(); * ``` * * To run `callback` *before* the sleep happens, set `fireBeforeWait`: * ```js * continuously(callback, intervalMs, { fireBeforeWait: true }); * ``` * @param callback - Function to run. If it returns _false_, loop exits. * @param options - {@link ContinuouslyOpts ContinuouslyOpts} * @param interval - Speed of loop (default: 0) * @returns Instance to control looping. * @see {@link Timeout} if you want to trigger something once. */ declare const continuously: (callback: ContinuouslyAsyncCallback | ContinuouslySyncCallback, interval?: Interval, options?: Partial<ContinuouslyOpts>) => Continuously; export { type Continuously as C, type OnStartCalled as O, type ContinuouslyAsyncCallback as a, type ContinuouslyOpts as b, type ContinuouslySyncCallback as c, continuously as d };