Skip to content

Instantly share code, notes, and snippets.

@j3k0
Last active October 28, 2022 02:24
Show Gist options
  • Save j3k0/1ec24f8b6a2a964d0c56738665ab0bc1 to your computer and use it in GitHub Desktop.
Save j3k0/1ec24f8b6a2a964d0c56738665ab0bc1 to your computer and use it in GitHub Desktop.
setTimeout based on the audioContext timer
function customTimeoutFunction(audioContext) {
let tasks = [];
let nextTaskId = 1;
function now() {
return audioContext.currentTime * 1000;
}
function scheduler() {
const currentTime = now();
// Call due tasks
tasks.forEach(function(task) {
if (task.due <= currentTime)
task.fn();
});
// Then remove them from the list.
tasks = tasks.filter(function(task) { return task.due > currentTime; });
// More tasks pending, keep calling the scheduler.
if (tasks.length > 0) {
window.requestAnimationFrame(scheduler);
}
}
return {
setTimeout: function(fn, delayMillis) {
const id = nextTaskId;
nextTaskId += 1;
tasks.push({
id: id,
due: now() + delayMillis,
fn: fn
});
if (tasks.length === 1) {
window.requestAnimationFrame(scheduler);
}
return id;
},
clearTimeout: function(id) {
tasks = tasks.filter(function(t) { return t.id !== id; });
}
}
}
function customTimeout(audioContext) {
let tasks = [];
let nextTaskId = 1;
let t0 = 0;
let now = 0;
function updateInternalTime() {
const t1 = audioContext.currentTime * 1000; // somehow
const deltaT = t1 - t0;
if (deltaT < 0) { // the time counter was reset?
return; // don't increase time.
}
if (deltaT > 1000) { // the app was backgrounded or frozen
deltaT = 1000; // don't allow big jumps in time
}
now += deltaT;
}
function scheduler() {
updateInternalTime();
// Call due tasks
tasks.forEach(function(task) {
if (task.due <= now)
task.fn();
});
// Then remove them from the list.
tasks = tasks.filter(function(task) { return task.due > now; });
// More tasks pending, keep calling the scheduler.
if (tasks.length > 0) {
t0 = audioContext.currentTime * 1000;
window.requestAnimationFrame(scheduler);
}
}
return {
setTimeout: function(fn, delayMillis) {
const id = nextTaskId;
nextTaskId += 1;
tasks.push({
id: id,
due: now + delayMillis,
fn: fn
});
if (tasks.length === 1) {
t0 = audioContext.currentTime * 1000;
window.requestAnimationFrame(scheduler);
}
return id;
},
clearTimeout: function(id) {
tasks = tasks.filter(function(t) { return t.id !== id; });
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment