Skip to content

Instantly share code, notes, and snippets.

@dmitrydwhite
Created September 21, 2016 04:11
Show Gist options
  • Save dmitrydwhite/ac48e8c51db60262bc244b8720c359a5 to your computer and use it in GitHub Desktop.
Save dmitrydwhite/ac48e8c51db60262bc244b8720c359a5 to your computer and use it in GitHub Desktop.
// TODO: Add semicolon at end of this and all the other statements.
// TODO: Move module.exports statement to bottom of file--not necessary, but best practice.
module.exports = Batch
/**
* Creates a new instance of Batch
* @param {Boolean} sync Whether or not a delay frame should be set during queueing.
*/
function Batch(sync) {
if(!(this instanceof Batch)) {
return new Batch(sync)
}
// Set instance properties
this.jobs = []
this.sync = sync
this.frame = null
// TODO: Calling bind on run doesn't seem necessary here.
this.run = this.run.bind(this)
}
// Add methods to the class
Batch.prototype.request_frame = request_frame
Batch.prototype.queue = queue
Batch.prototype.add = add
Batch.prototype.run = run
/**
* Adds the passed function to the queue of jobs to run.
* @param {Function} fn Function to add to the queue.
*/
function add(fn) {
// TODO: Declare each var on its own line; short of that, place the comma on the end of line.
var queued = false
, batch = this
, self
, args
return queue
/**
* [queue description]
* @return {[type]} [description]
*/
function queue() {
// TODO: Both this function and `run` below have duplicated names with methods on Batch. This shouldn't
// affect functionality as scope is different, but having more unique names for these two may improve
// comprehension and make more future-proof.
args = [].slice.call(arguments)
self = this
if(!queued) {
queued = true
batch.queue(run)
}
}
/**
* Sets the scope of the function passed to `add` to the global scope.
* TODO: Is it supposed to be doing this?
*/
function run() {
queued = false
fn.apply(self, args)
}
}
/**
* Adds the passed function to the class jobs array; requests frame if sync is true;
* @param {Function} fn Callback to add to the queue.
*/
function queue(fn) {
this.jobs.push(fn)
if(!this.sync) {
this.request_frame()
}
}
/**
* Iterates through the array of queued jobs and executes each one in order.
*/
function run() {
var jobs = this.jobs
this.jobs = []
this.frame = null
// TODO: var l is only used once; it could be replaced with jobs.length.
for(var i = 0, l = jobs.length; i < l; ++i) {
jobs[i]()
}
}
/**
* Sets class prop frame to delay the execution of Batch.run if Batch.frame isn't defined.
*/
function request_frame() {
// Return if frame has already been set.
if(this.frame) {
return
}
// Otherwise, set frame to the delay function.
this.frame = requestAnimationFrame(this.run)
}
/**
* Sets delay function based on availability in order; invokes passed callback
* @param {Function} callback The method to pass on to the delaying function
* @return {*} The invoked delaying function
*/
function requestAnimationFrame(callback) {
// TODO: We should probably check for the existence of `global` before we check props on it.
var raf = global.requestAnimationFrame ||
global.webkitRequestAnimationFrame ||
global.mozRequestAnimationFrame ||
timeout
return raf(callback)
/**
* Wrapper for setTimeout with given delay.
* @param {Function} callback Function to invoke after delay
* @return {Number} Timeout ID
*/
function timeout(callback) {
// TODO: For clarity, move this function statement above the outer function's return statement.
// TODO: The delay here seems like a magic number; perhaps do the math outright, and set this as a class
// constant in the constructor or on the prototype.
return setTimeout(callback, 1000 / 60)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment