Skip to content

Instantly share code, notes, and snippets.

@ccnokes
Last active February 23, 2019 22:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccnokes/d6ef6ad42e46a1bf475823267c8c3a52 to your computer and use it in GitHub Desktop.
Save ccnokes/d6ef6ad42e46a1bf475823267c8c3a52 to your computer and use it in GitHub Desktop.
RequestIdleCallback scheduler. Create an instance and use it globally to ensure that tasks are efficiently run in as few requestIdleCallbacks as possible (as described here https://developers.google.com/web/updates/2015/08/using-requestidlecallback). Sandbox: https://codesandbox.io/s/r45rv9lv1o
class RICScheduler {
private queue: { task: () => void, id: number }[] = [];
private running = false;
private nextId = 0;
private ricId;
private id() {
return this.nextId++;
}
// returns unsubscribe function
add(fn: () => void) {
let taskConfig = { task: fn, id: this.id() };
this.queue.push(taskConfig);
if (!this.running) {
this.run();
}
return () => this.cancel(taskConfig.id);
}
private cancel(id: number) {
let index = this.queue.findIndex(item => item.id === id);
if (index !== -1) {
this.queue.splice(index, 1);
}
}
clearAll() {
cancelIdleCallback(this.ricId);
this.queue = [];
this.running = false;
}
private run() {
this.running = true;
this.ricId = requestIdleCallback((deadline) => {
let taskCount = 0;
while (deadline.timeRemaining() > 0 && this.queue.length) {
let { task } = this.queue.shift();
task();
taskCount++;
}
// if there's still tasks remaining, schedule another run
if (this.queue.length > 0) {
this.run();
} else {
this.running = false;
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment