import { AsyncIterableX } from './asynciterablex.js'; import { sleep } from './_sleep.js'; import { throwIfAborted } from '../aborterror.js'; class GenerateTimeAsyncIterable extends AsyncIterableX { private _initialState: TState; private _condition: (value: TState, signal?: AbortSignal) => boolean | Promise; private _iterate: (value: TState, signal?: AbortSignal) => TState | Promise; private _resultSelector: (value: TState, signal?: AbortSignal) => TResult | Promise; private _timeSelector: (value: TState, signal?: AbortSignal) => number | Promise; constructor( initialState: TState, condition: (value: TState, signal?: AbortSignal) => boolean | Promise, iterate: (value: TState, signal?: AbortSignal) => TState | Promise, resultSelector: (value: TState, signal?: AbortSignal) => TResult | Promise, timeSelector: (value: TState, signal?: AbortSignal) => number | Promise ) { super(); this._initialState = initialState; this._condition = condition; this._iterate = iterate; this._resultSelector = resultSelector; this._timeSelector = timeSelector; } async *[Symbol.asyncIterator](signal?: AbortSignal) { throwIfAborted(signal); for ( let i = this._initialState; await this._condition(i, signal); i = await this._iterate(i, signal) ) { const time = await this._timeSelector(i, signal); await sleep(time, signal); yield await this._resultSelector(i, signal); } } } /** * Generates an async-iterable sequence by running a time-based state-driven loop producing the sequence's elements. * * @template TState The type of the state used in the generator loop. * @template TResult The type of the elements in the produced sequence. * @param {TState} initialState The initial state. * @param {((value: TState, signal?: AbortSignal) => boolean | Promise)} condition Condition to terminate generation (upon returning false). * @param {((value: TState, signal?: AbortSignal) => TState | Promise)} iterate Iteration step function. * @param {((value: TState, signal?: AbortSignal) => TResult | Promise)} resultSelector Selector function for results produced in * the sequence. * @param {((value: TState, signal?: AbortSignal) => number | Promise)} timeSelector Selector function for how much time to wait. * @returns {AsyncIterableX} The generated async-iterable sequence. */ export function generateTime( initialState: TState, condition: (value: TState, signal?: AbortSignal) => boolean | Promise, iterate: (value: TState, signal?: AbortSignal) => TState | Promise, resultSelector: (value: TState, signal?: AbortSignal) => TResult | Promise, timeSelector: (value: TState, signal?: AbortSignal) => number | Promise ): AsyncIterableX { return new GenerateTimeAsyncIterable( initialState, condition, iterate, resultSelector, timeSelector ); }