diff --git a/README.md b/README.md index c5f3301..63f9a23 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,14 @@ function startTimeout(timerFunc: Function, start: TimeUntil): StopFunction ### startInterval -The `startInterval` method starts an interval that calls a given function repeatedly with a fixed time delay between each call. Like `startTimeout`, the initial delay is calculated based on a `TimeUntil` object. The method returns a `StopFunction` (see below). +The `startInterval` method starts an interval that calls a given function repeatedly with a fixed time delay between each call. Like `startTimeout`, the initial delay is calculated based on a `TimeUntil` object. If called with `callbackAfterTimeout` set to `true`, it will call the callback function after the timeout has finished running (right when starting the interval). The method returns a `StopFunction` (see below). ```typescript function startInterval( intervalFunc: Function, intervalMS: number, start?: TimeUntil + callbackAfterTimeout: boolean = false ): StopFunction ``` diff --git a/src/Scheduler.ts b/src/Scheduler.ts index 54a51d5..9719ead 100644 --- a/src/Scheduler.ts +++ b/src/Scheduler.ts @@ -26,7 +26,12 @@ export type StopCancelFunction = (stopRunning?: boolean) => void export type StopFunction = (stopTime?: TimeUntil) => StopCancelFunction | null -function timeUntil(start: TimeUntil) { +/** + * Used to convert a TimeUntil object into a number of milliseconds + * @param {TimeUntil} start + * @return {number} delay + */ +function timeUntil(start: TimeUntil): number { if (start.ms) { return start.ms } @@ -76,10 +81,15 @@ export function startTimeout( timeout = setTimeout(function () { // Clear the timeout variable timeout = null + // call the function immediately timerFunc() }, delay) + /** + * Cleanup function + * @return {void} + */ const stopNow = () => { if (timeout) clearTimeout(timeout) } @@ -95,6 +105,7 @@ export function startTimeout( return null } + // Set a timeout to stop the timeout at the target time const stopTimeout = setTimeout(stopNow, timeUntil(stopTime)) /** @@ -102,7 +113,7 @@ export function startTimeout( * @param {boolean} stopRunning - optional * @return void */ - return (stopRunning?: boolean) => { + return (stopRunning: boolean = false) => { clearTimeout(stopTimeout) if (stopRunning) stopNow() } @@ -117,26 +128,40 @@ export function startTimeout( * @param {Function} intervalFunc * @param {number} intervalMS * @param {TimeUntil} start - optional + * @param {boolean} callbackAfterTimeout - optional * @return {StopFunction} */ export function startInterval( intervalFunc: Function, intervalMS: number, - start?: TimeUntil + start?: TimeUntil, + callbackAfterTimeout: boolean = false ): StopFunction { let delay = start ? timeUntil(start) : 0 // set a timeout to start the interval at the target time - let interval: number | null = null - let timeout: NodeJS.Timeout | null = setTimeout(function () { - // Clear the timeout variable - timeout = null - // start the interval - interval = setInterval(intervalFunc, intervalMS) - // call the function immediately - intervalFunc() - }, delay) + let interval: number | null = + delay === 0 ? setInterval(intervalFunc, intervalMS) : null + let timeout: NodeJS.Timeout | null = + delay > 0 + ? setTimeout(function () { + // Clear the timeout variable + timeout = null + // start the interval + interval = setInterval(intervalFunc, intervalMS) + + // Invoke the callback, just because the timer expired (so at the beginning of the interval) + if (callbackAfterTimeout) { + intervalFunc() + } + }, delay) + : null + + /** + * Cleanup function + * @return {void} + */ const stopNow = () => { if (timeout) clearTimeout(timeout) if (interval) clearInterval(interval) @@ -160,7 +185,7 @@ export function startInterval( * @param {boolean} stopRunning - optional * @return void */ - return (stopRunning?: boolean) => { + return (stopRunning: boolean = false) => { clearTimeout(stopTimeout) if (stopRunning) stopNow() }