78 lines
2.6 KiB
TypeScript
78 lines
2.6 KiB
TypeScript
if (global.wrappedTimers === undefined) {
|
|
global.wrappedTimers = new Map();
|
|
}
|
|
|
|
export type WrappedTimer = { timer: Timer | undefined; running: boolean; };
|
|
export type WrappedTimerResult = { callback: ReturnType<typeof getCallbackHandler>; wrappedTimer: WrappedTimer; };
|
|
|
|
/**
|
|
* Create a callback handler for a wrapped timer that prevents the callback from running if it is already running
|
|
* and prevents the callback from running if it is already running.
|
|
* @template TArgs
|
|
* @param {string} key unique identifier for the timer
|
|
* @param {(...args: Array<TArgs>) => (Promise<void> | void)} callback function to run
|
|
* @param {Array<TArgs>} args arguments to pass to the callback
|
|
* @returns {() => Promise<void>}
|
|
*/
|
|
function getCallbackHandler<TArgs>(key: string, callback: (...args: Array<TArgs>) => (Promise<void> | void), ...args: Array<TArgs>): () => Promise<void> {
|
|
return async () => {
|
|
const thisTimer = global.wrappedTimers.get(key);
|
|
if (thisTimer === undefined) {
|
|
console.debug(`Wrapped timer ${key} does not exist`);
|
|
return;
|
|
}
|
|
if (thisTimer.running) {
|
|
console.debug(`Wrapped timer ${key} is already running`);
|
|
return;
|
|
}
|
|
|
|
try {
|
|
thisTimer.running = true;
|
|
await callback(...args);
|
|
} catch (e) {
|
|
console.error(e);
|
|
} finally {
|
|
thisTimer.running = false;
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Create a wrapped timer aka interval
|
|
* @template TArgs
|
|
* @param {string} key unique identifier for the timer
|
|
* @param {number} interval in milliseconds
|
|
* @param {(...args: Array<TArgs>) => (Promise<void> | void)} callback function to run
|
|
* @param {Array<TArgs>} args arguments to pass to the callback
|
|
* @returns {WrappedTimerResult}
|
|
*/
|
|
export function createWrappedTimer<TArgs>(key: string, callback: (...args: Array<TArgs>) => (Promise<void> | void), interval: number, ...args: Array<TArgs>): WrappedTimerResult {
|
|
const thisTimer = global.wrappedTimers.get(key);
|
|
const handler = getCallbackHandler(key, callback, ...args);
|
|
|
|
if (thisTimer !== undefined) {
|
|
console.debug(`Wrapped timer ${key} already exists, clearing timer`);
|
|
clearInterval(thisTimer.timer);
|
|
console.debug(`Wrapped timer ${key} set with interval ${interval}ms`);
|
|
thisTimer.timer = setInterval(handler, interval);
|
|
|
|
return {
|
|
callback: handler,
|
|
wrappedTimer: thisTimer,
|
|
};
|
|
}
|
|
|
|
console.debug(`Wrapped timer ${key} created with interval ${interval}ms`);
|
|
|
|
const wrappedTimer: WrappedTimer = {
|
|
timer: setInterval(handler, interval),
|
|
running: false,
|
|
};
|
|
|
|
global.wrappedTimers.set(key, wrappedTimer);
|
|
|
|
return {
|
|
callback: handler,
|
|
wrappedTimer,
|
|
};
|
|
}
|