Skip to content

Instantly share code, notes, and snippets.

@thysultan
Last active January 23, 2017 11:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thysultan/3761df3e73d0092baa0527a83c35a5aa to your computer and use it in GitHub Desktop.
Save thysultan/3761df3e73d0092baa0527a83c35a5aa to your computer and use it in GitHub Desktop.
function frameScheduler (fps) {
var highPriWork = [];
var lowPriWork = [];
var highPriWorkLen = 0;
var lowPriWorkLen = 0;
var frameBudget = 1000 / fps;
var lastTime = 0;
var asyncCallback;
var Promise = window.Promise;
var requestAnimationFrame = window.requestAnimationFrame;
var promiseSupport = Promise !== void 0;
var requestAnimationFrameSupport = requestAnimationFrame !== void 0;
if (promiseSupport) {
asyncCallback = function asyncCallback (callback) { Promise.resolve().then(callback); }
} else if (requestAnimationFrameSupport) {
asyncCallback = function asyncCallback (callback) { requestAnimationFrame(callback); }
} else {
asyncCallback = function asyncCallback (callback) { setTimeout(callback, 0); }
}
function flushWork (highPriority) {
var task = highPriority ? highPriWork.shift() : lowPriWork.shift();
var func = task[0];
var length = task[1];
var args = length !== 0 ? task[2] : null;
var context = task[3];
switch (length) {
case 0: func.call(context); break;
case 1: func.call(context, args[0]); break;
case 2: func.call(context, args[0], args[1]); break;
case 3: func.call(context, args[0], args[1], args[2]); break;
case 4: func.call(context, args[0], args[1], args[2], args[3]); break;
case 5: func.call(context, args[0], args[1], args[2], args[3], args[4]); break;
case 6: func.call(context, args[0], args[1], args[2], args[3], args[4], args[5]); break;
}
}
function throttleWork () {
var time = Date.now();
var delta = time - lastTime;
if (delta > frameBudget) {
lastTime = time - (delta % frameBudget);
if (highPriWorkLen !== 0) {
flushWork((highPriWorkLen--, true));
} else if (lowPriWorkLen !== 0) {
flushWork((lowPriWorkLen--, false));
}
} else if (highPriWorkLen !== 0 || lowPriWorkLen !== 0) {
asyncCallback(throttleWork);
}
}
/**
* @param {boolean} highPriority
* @param {function} func
* @param {number} length - number of arguments passed to func
* @param {args} args - arguments passed to func
* @param {context} context - the this context to execute the function with
*/
return function assignWork (highPriority, func, length, args, context) {
if (highPriority) {
highPriWork[highPriWorkLen++] = [func, length, args, context];
} else {
lowPriWork[lowPriWorkLen++] = [func, length, args, context];
}
asyncCallback(throttleWork);
}
}
@thysultan
Copy link
Author

a visualisation of work timeline cycles - https://codepen.io/thysultan/pen/VPboOB.

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