I have written a small helper function to make delayed sequential function execution easier.

We have the following case: we need to execute an array of functions. The second one has to execute after the first one finishes, the third after the second and so one. The scenario gets a bit more complicated when wee need some delay between functions. So we have to execute function 1, then after it finishes, wait for 200 ms, and execute function 2, then after another 500 ms execute function 3 and so on.

So the code is the following:

function runSequence(arr, scope, delay){
	arr.push(function(){});
	delay = delay || 0;

	var i = 0,
             len = arr.length;

	for(;i < len-1; i++){
		(function(index, thisObject){
			arr[index] = function(){
				var isFn = !!thisObject.call,
					fn = isFn? thisObject : thisObject.fn,
					fnScope = isFn? scope: thisObject.scope,
					fnDelay = isFn? delay : thisObject.delay,
					fnToExecute = function(){ fn.call(this); arr[index+1](); }

                                fnScope = fnScope || this;
				fnDelay? setTimeout(function(){ fnToExecute.call(fnScope) }, fnDelay) : fnToExecute.call(fnScope);
			}
		})(i, arr[i]);
	}

	arr[0]();
}

We can do the following:

runSequence([
	{ fn: function(){ console.log('executed immediately') }, delay: 0 },
	{ 
          fn: function(){ console.log('this was after 1500 ms, with scope: ', this.name) }, 
          delay: 1500, 
          scope: {name: 'sequence running'} 
        },
	{ fn: function(){ console.log('this was after 2s ') }, delay: 2000 }
], this)
/*
 * The first and the last functions above are executed in the scope of the code executing the runSequence function
 * The second function is instead called with the scope being the passed object, {name: 'sequence running'} 
 */

or the following:

runSequence([
	function(){ console.log('first after 200ms') },
	function(){ console.log('yet another 200 ms') },
	function(){ console.log('the last fn at 200ms') }
], this, 200)
/*
 * A shorter form of the runSequence function call, with functions running at equal timeouts, in the passed 'this' scope
 */

This function can be useful when processing large amounts of data that would otherwise block the browser, or in cases when one would need to trigger ajax calls with a certain delay in between. I’m sure that there are other cases when this could prove useful.
In the case of processing large amounts of data, one could use this to fill up a (non-paginated) grid with data, in chunks of, say, 200 records.

Do you find this pattern useful?

Well, if you are programming in JavaScript for a while, you are familiar with the arguments ‘array’ which gives you access to function arguments by index, without the need of argument names. And if you are programming JavaScript for a bit longer while, you will know that arguments is not even a normal array. It does not have any methods of an array. You can just use it to access items by index and also access it’s length property. That’s all. What if you want to make a copy of the array? What if you want to push or pop items? Well… you have some work to do… OR …

Or do something smart. Like call the slice method from Array.prototype on the arguments, something like:

//this makes a copy of the arguments and returns a true array
Array.prototype.slice.call(arguments, 0) 

//pushes the value '5' in the arguments
Array.prototype.push(arguments, 5) 
//this is not valid: arguments.push(5)

Well, maybe most of you expert JavaScript programmers have thought about this, and this is not a news. But, let’s share from our experience to the more novice/newcomers to JavaScript and show them the beauty of this language!

JavaScript is a great language! It’s expressive! It’s powerful! That’s why we love JavaScript.

What is really fascinating about JavaScript is it’s dynamic nature. You can dynamically change the behaviour of the code… even not your code. While this is really powerful, it can be also a pain if not used with care.

Well, let’s do something practical now. I want to intercept every log message in my js application. As people usually use Firebug (and if you’re not using it… well, you should, so start right here), the javascript code is populated with console.log or console.warn messages. Say we want to execute a function before and after console.log is called. Test the following code within firebug.

var backup = console.log;

function beforeLog(){
    backup('before log:',arguments);
}

function afterLog(){
    backup('after log:',arguments);
}

console.log = function(){
    beforeLog.apply(this,arguments);
    backup.apply(this,arguments);
    afterLog.apply(this,arguments);
}

console.log('hello','world');

In the first place, make a backup to the function we want to intercept.

Second, just redefine the function… and we usually want to execute the old function (so here is where we need the backup) and perform some additional things as well. Placing the code at the beginning of your coolest app changes the behaviour of all the log messages you have.

I found this useful when going from a development environment to a live environment. The best choice would be to use a build system to comment out (or even better, delete) all the console.log() calls. But a quick fix when going live is the following:

if (!window.console){
   /*
    * for users who do not have firebug installed, 
    * just define a "mock" console object
    */
    window.console = {};
}
window.console.log = function(){};
console.log('hello world'); // call to an empty function

This is just a simple use of dynamically changing the behaviour of existing code. What about you? How do you intercept function calls? Waiting for some nice suggestions.