UNPKG

loop-controller

Version:
106 lines (105 loc) 3.8 kB
import { Waiter } from "state-waiter"; export type LoopControllerDeps<T> = { initialArray: T[]; makePromise: (elm: T) => Promise<unknown>; autoStart?: boolean; onStart?: () => void; onStop?: () => void; onError?: (error: unknown) => void; }; type States = "running" | "pausing" | "paused" | "done"; type Events = "iteration-done"; /** * Controls serial execution of promises made from elements of an array. * * - Takes an array and a function that makes a promise for each element in the array. * - Ensures that it's possible to use the following operations: * - pause * - resume * * Terminology * - loop-promise: Will resolve when all elements have been processed. See `this.getPromise` * - pause-promise: Will resolve when a pause operation succeeds. I.e. when the current iteration is done, and execution stops. * * Features * - Pause-promise can resolve with either "paused" or "cancelled". * - It resolves with paused if the current iteration is finised before a new resume operation arrives * - It resolves with cancelled if a resume operation arrives before the current iteration finishes. * - If an iteration throws an error the execution will stop. * - Both loop and pause promise will be rejected in case of error. * * impl * - When pausing at last iteration, the state will become "paused", and the loop-promise will not resolve, * until resume is called. Maybe that should change? */ export declare class LoopController<T> { private deps; waiter: Waiter<States, Events>; private curIdx; private arr; private loopProm; private pauseProm?; /** * */ constructor(deps: LoopControllerDeps<T>); /** * */ isRunning: () => boolean; /** * Return the loop-promise. * * note * this isn't really compatible with: setArray and prependArray. Some semantic needs to be defined. */ getPromise: () => Promise<void>; /** * Replace the underlying array. * * - Calling this, will not start execution. Call resume afterwards to do that. * - If executing, the new array will be used after the current iteration is done. * - A new loop promise is created, because the exsisting elements are dropped. Their loop will never resolve. */ setArray: (arr: T[]) => void; /** * Prepend an array in front of the remaining elements. * * - The new array will be executed before the remaining elements from the old array. * The then the old array will continue executing, as originally planed. */ prependArray: (arr: T[]) => void; /** * Pause execution * * - It's okay to pause, when already pausing, it's a no-op. * - If already paused, a promise is returned, that resolve to "paused" next tick. * - A promise is returned, that resolves to "paused" when pause state is reached. Or "cancelled" if a resume operation * cancels the pause before current iteration is done. * - Pausing again will return the same promise as before, if pause state hasn't been reached since last pause operation. */ pause: () => Promise<"paused" | "cancelled">; /** * Resume execution * * - It's okay to resume, when already running, it's a no-op. * - Resume resolves the pause-promise with: "cancelled". * - If the loop isn't running at all, e.g. wasn't auto-started, resume will simply start the loop. */ resume: () => undefined; /** * * impl * important that `this.arr` and `curIdx` is used in one tick only. Because it can change at any time. */ private tryRunNextTest; /** * */ private onIterationError; /** * */ private onIterationDone; } export {};