@lodestar/utils
Version:
Utilities required across multiple lodestar packages
88 lines (73 loc) • 2.21 kB
text/typescript
import {ErrorAborted, TimeoutError} from "./errors.js";
export type WaitForOpts = {
/** Time in milliseconds between checking condition */
interval?: number;
/** Time in milliseconds to wait before throwing TimeoutError */
timeout?: number;
/** Abort signal to stop waiting for condition by throwing ErrorAborted */
signal?: AbortSignal;
};
/**
* Wait for a condition to be true
*/
export function waitFor(condition: () => boolean, opts: WaitForOpts = {}): Promise<void> {
return new Promise((resolve, reject) => {
const {interval = 10, timeout = Infinity, signal} = opts;
if (signal?.aborted) {
return reject(new ErrorAborted());
}
if (condition()) {
return resolve();
}
let onDone: () => void = () => {};
const timeoutId = setTimeout(() => {
onDone();
reject(new TimeoutError());
}, timeout);
const intervalId = setInterval(() => {
if (condition()) {
onDone();
resolve();
}
}, interval);
const onAbort = (): void => {
onDone();
reject(new ErrorAborted());
};
if (signal) signal.addEventListener("abort", onAbort);
onDone = () => {
clearTimeout(timeoutId);
clearInterval(intervalId);
if (signal) signal.removeEventListener("abort", onAbort);
};
});
}
export interface ElapsedTimeTracker {
(): boolean;
msSinceLastCall: number;
}
/**
* Create a tracker which keeps track of the last time a function was called
*
* @param durationMs
* @returns
*/
export function createElapsedTimeTracker({minElapsedTime}: {minElapsedTime: number}): ElapsedTimeTracker {
// Initialized with undefined as the function has not been called yet
let lastTimeCalled: number | undefined = undefined;
function elapsedTimeTracker(): boolean {
const now = Date.now();
const msSinceLastCall = now - (lastTimeCalled ?? 0);
if (msSinceLastCall > minElapsedTime) {
// Do not reset timer if called before timer elapsed
lastTimeCalled = now;
return true;
}
return false;
}
return Object.assign(elapsedTimeTracker, {
get msSinceLastCall() {
return Date.now() - (lastTimeCalled ?? 0);
},
});
}