Matt Snider JavaScript Resource

Understanding JavaScript and Frameworks

Saturday, November 3, 2007

Batch Function

I introduced another pattern into the Event package and wanted to explain its mechanics, before introducing it. I attached this to my Core package (Core.batch).

A batch Function is a powerful tool used for replacing/simplifying ‘for’ loops. Anytime you are iterating on each element in an Array or Array-like structure, then you can use a batch function in its stead. A batch function will perform the iteration for you and pass the value of the element at index, the index, and any additional parameters into the function you provide it. Here is my current batch Function:

/** * Executes fn on each element in the set * * @method batch * @param set {array} the collection to iterate on * @param fn {function} the function to execute on each member of the collection; iterator function * @param {arguments} any number of arguments to pass into fn * @public */ batch: function(set, fn) { if (! set.length) {return;} var args = Array.prototype.slice.apply(arguments, [2]); args.unshift(null, null); // iterate on the items, executing the function, and stoping when function returns true or touched all childnodes for (var i = 0, j = set.length; i < j; i++) { args[0] = set[i]; args[1] = i; if (fn.apply(this, args)) { return; } } },

The first line ensures that the ’set’ is iterable. If it is not, then we return undefined. Next we leverage the ’slice’ method of the Array prototype on the arguments, which always returns an array, so any array-like Object (nodelists, arguments, etc.) becomes an array. We trim out the first two values of the arguments, which are the parameters: “set” and “fn”, and assign the result to ‘args’. Two empty elements are pushed into the front of the ‘args’. As we iterate through the set, we put values into the first two members of ‘args’ (0: value at index, 1: index). All other parameters passed into batch, those after ’set’ and ‘fn’, will also be passed into the iterator function as parameters using the apply method. The last part is to test the results of the iterator function and stop the batch process anytime it returns true. This way you do not always need to iterate on every member of the array.

Now, to see batch in action, suppose you have a ‘attachEventToSet’. This Function iterates through an Array and calls ‘attachEvent’ on each member of the Array.

attachEventToSet: function(set, eType, fn, capture) { for (var i = 0, j = set.length; i < j; i++) { Event.attachEvent(set[i], eType, fn, capture); } },

this could be simplified to:

attachEventToSet: function(set, eType, fn, capture) { Core.batch(function(el, i) { Event.attachEvent(el, eType, fn, capture); }); },

The definition of the inner Function inside of the attachEventToSet Function closure, provides access to the parameters: eType, fn, and capture. It you so choose, you could have also written the batch, as follows:

attachEventToSet: function(set, eType, fn, capture) { Core.batch(function(el, i, eType, fn, capture) { Event.attachEvent(el, eType, fn, capture); }, eType, fn, capture); },

Here, you are passing extra parameters through the batch Function and assigning them directly to the inner Function, instead of relying on the closure. Whenever possible, I usually use closures as the code is more concise.

Some possible areas of improvement are:

  • scope management - it may be useful execute the inner Function in a particular scope; I haven’t had a need to yet
  • validation - validate array and value of the array, also throw exceptions (or other error management) when bad parameters have been passed
  • quick functions - a small collection of common batch functions, such as comparison and update methods
posted by Matt Snider at 12:56 am  

2 Comments »

  1. Good post. See also YAHOO.util.Dom.batch (YUI) and Array.prototype.forEach (JS 1.6).

    Comment by David Golightly — November 4, 2007 @ 10:26 am

  2. Thanks david,

    I drew a some inspiration from the YUI batch function and prototypes array functions.

    Comment by admin — November 4, 2007 @ 12:42 pm

RSS feed for comments on this post. TrackBack URI

Leave a comment

Powered by WordPress