loop-controller
Version:
Controls serial execution of promises.
106 lines (105 loc) • 3.8 kB
TypeScript
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 {};