Timer functions in JS
PUBLISHED ON: Sunday, Aug 6, 2023
LAST UPDATED ON: Monday, Aug 14, 2023
Asynchronous version of setTimeout()
/**
* do something
* sleep(2000);
* do another thing
*/
export default async function sleep(duration: number): Promise<any> {
return new Promise((resolve) => {
setTimeout(resolve, duration);
});
}
setCancellableInterval()
export default function setCancellableInterval(
callback: Function,
delay?: number,
...args: Array<any>
): () => void {
const id = setInterval(() => {
callback(...args);
}, delay);
return () => {
clearInterval(id);
};
}
setCancellableTimeout()
export default function setCancellableTimeout(
callback: Function,
delay?: number,
...args: Array<any>
): () => void {
const id = setTimeout(() => {
callback(...args);
}, delay);
return () => {
clearTimeout(id);
};
}
setTimeout() polyfill
const timers: Record<number, { callback: Function, delay: number }> = {};
function generateID() {
return Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
}
function generateNewID() {
let id = generateID();
while (id in timers) {
id = generateID();
}
return id;
}
function _clearTimeout(id: number) {
if (id in timers) {
delete timers[id];
}
}
function check() {
if (Object.keys(timers).length <= 0) {
return;
}
for (let timerID in timers) {
const { callback, delay } = timers[timerID];
if (Date.now() > delay) {
callback();
_clearTimeout(+timerID);
}
}
requestIdleCallback(check);
}
function _setTimeout(
callback: Function,
delay?: number,
...args: any[]
) {
if (typeof callback !== "function") {
throw new Error("callback should be a function");
}
const timerID = generateNewID();
timers[timerID] = {
callback: () => callback(...args),
delay: Date.now() + (delay || 0),
}
if (Object.keys(timers).length === 1) {
requestIdleCallback(check);
}
return timerID;
}
window.requestIdleCallback
The window.requestIdleCallback()
method queues a function to be called during a browser's idle periods. This enables developers to perform background and low priority work on the main event loop, without impacting latency-critical events such as animation and input response.
Functions are generally called in first-in-first-out order; however, callbacks which have a timeout specified may be called out-of-order if necessary in order to run them before the timeout elapses.
setInterval() polyfill
let intervals: Record<number, number> = {};
function _clearInterval(intervalID: number) {
if (intervalID in intervals) {
delete intervals[intervalID];
}
}
function _setInterval(
callback: Function,
delay?: number,
...args: any[]
) {
const id = generateNewID();
function repeat() {
intervals[id] = _setTimeout(() => {
callback(...args);
if (id in intervals) {
_clearInterval(intervals[id]);
repeat();
}
}, delay);
}
repeat();
return id;
}