Skip to content

Instantly share code, notes, and snippets.

@bitsmanent
Last active May 13, 2024 15:26
Show Gist options
  • Save bitsmanent/7f562f864205d9164c7412a3aa96773d to your computer and use it in GitHub Desktop.
Save bitsmanent/7f562f864205d9164c7412a3aa96773d to your computer and use it in GitHub Desktop.
Set and cancel timers which can be paused and resumed
(() => {
"use strict";
/* Why don't overwrite setTimeout()? It's doable but...
* https://www.adequatelygood.com/Replacing-setTimeout-Globally.html
* Also we may want to keep running high priority timers one day. */
const timers = [];
const state = {
paused: false,
index: 0,
};
function setTimer(cb, delay) {
const id = ++state.index;
const expire = (new Date).getTime() + delay;
const timer = {id,cb,delay,expire};
timers.push(timer);
if(!state.paused)
schedule(id);
return id;
}
function schedule(id) {
const timer = timers.find(x => x.id == id);
if(!timer)
return;
timer.tm = setTimeout(() => {
timer.cb();
delete timer.tm;
clearTimer(id);
}, timer.delay)
}
function clearTimer(id) {
const timer = timers.find(x => x.id == id);
let index;
if(!timer)
return;
if(timer.tm)
clearTimeout(timer.tm);
index = timers.findIndex(x => x.id == id);
timers.splice(index, 1);
}
function clearAllTimers() {
timers.forEach(x => clearTimer(x.id));
}
function pauseAll() {
state.paused = true;
timers.forEach(timer => {
clearTimeout(timer.tm);
delete timer.tm;
});
}
function resumeAll() {
state.paused = false;
timers.forEach(timer => {
const time = (new Date()).getTime();
timer.delay = timer.expire - time;
if(timer.delay < 0)
timer.delay = 0;
schedule(timer.id);
});
}
/* public */
Object.assign(window, {
pauseAll,
resumeAll,
setTimer,
clearTimer,
clearAllTimers
});
})();
@bitsmanent
Copy link
Author

bitsmanent commented May 3, 2024

Sample usage:

addEventListener("visibilitychange", () => {
  const visible = document.visibilityState == "visible";
  
  if(visible)
    return resumeAll();
  return pauseAll();
});

Have fun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment