Skip to content

Instantly share code, notes, and snippets.

@ededejr
Last active February 6, 2024 05:22
Show Gist options
  • Save ededejr/2fdafcc38d4e390b14abc52b5055bdae to your computer and use it in GitHub Desktop.
Save ededejr/2fdafcc38d4e390b14abc52b5055bdae to your computer and use it in GitHub Desktop.
a simple non-blocking wrapper around setTimeout
interface TickerConfig {
fn: () => Promise<void>;
intervalMs?: number;
firstRunDelay?: number;
}
class Ticker {
private fn: () => Promise<void>;
private timer?: NodeJS.Timeout;
private firstRunDelay = 1000 * 4;
private intervalMs = 1000 * 15;
constructor(config: TickerConfig) {
this.fn = config.fn;
this.intervalMs = config.intervalMs || this.intervalMs;
this.firstRunDelay = config.firstRunDelay || this.firstRunDelay;
}
start(): void {
this.scheduleNextExecution(this.firstRunDelay);
}
stop(): void {
if (this.timer) {
clearTimeout(this.timer);
this.timer = undefined;
}
}
private scheduleNextExecution(delay: number): void {
const milliseconds = Math.max(delay || 0);
this.timer = setTimeout(async () => this.execute(), milliseconds);
// unblock the event loop so if the parent process is finished
// it may exit.
this.timer.unref();
}
private async execute(): Promise<void> {
try {
await this.fn();
} catch {
// noop, this insulates from implosion
} finally {
this.scheduleNextExecution(this.intervalMs);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment