Last active
January 23, 2017 11:06
-
-
Save thysultan/3761df3e73d0092baa0527a83c35a5aa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
a visualisation of work timeline cycles - https://codepen.io/thysultan/pen/VPboOB.