1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
var Delayer = function(){ var l_args = []; var l_callback = null; var lag = 500; // microsecond of delay var end = null; var tid = false; var mcnow = function(){ var curDate = new Date(); return curDate.getTime(); }; this.put = function(){ l_callback = arguments[0]; l_args = []; for (var i = 1; i < arguments.length; i++) { l_args.push(arguments[i]); } end = mcnow() + lag; if (tid === false) { tid = setInterval(function(){ if (mcnow() > end) { l_callback.apply(null, l_args); clearInterval(tid); tid = false; } }, 10); } return true; }; }; // eample : var delayer = new Delayer(); delayer.put(function(){alert('1');}); delayer.put(function(){alert('2');}); delayer.put(function(){alert('3');}); delayer.put(function(){alert('4');}); delayer.put(function(){alert('5');}); delayer.put(function(){alert('6');}); delayer.put(function(){alert('7');}); // execute only this callback function after 500 microsecond (lag)
Refactorings
No refactoring yet !
Ants
June 10, 2010, June 10, 2010 11:23, permalink
Since I'm just a dilettante in JavaScript, maybe I'm missing a key concept or principle, but it seems to me, it would be better to use setTimeout() and clearTimeout() instead of the 10 microsecond polling the the code does above. It'll also let you get rid of the mcnow() function.
sgrezzeria
June 11, 2010, June 11, 2010 09:46, permalink
@Ants: I didn't use the setTimeout because the lag must restart every call.
Check the updated code because the previous version was nasty. Thanks and sorry
Ants
June 11, 2010, June 11, 2010 20:47, permalink
Yes, I understand that the lag must restart each call. But if on each call, you see that tid is false, you can call clearTimeout() with the tid, and then set tid to a new value when you call setTimeout(). Just like in your current source code, you only call setInterval() if tid is false.
sgrezzeria
June 12, 2010, June 12, 2010 09:26, permalink
Ok I undestand now!!!
good job! tnx!
your refactoring:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
var Delayer = function(){ var l_args = []; var l_callback = null; var lag = 1000; // microsecond of delay var end = null; var tid = false; var call = function(){ l_callback.apply(null, l_args); clearInterval(tid); tid = false; }; this.put = function(){ l_callback = arguments[0]; l_args = []; for (var i = 1; i < arguments.length; i++) { l_args.push(arguments[i]); } if (tid !== false) { clearInterval(tid); } tid = setInterval(call, lag); return true; }; };
Ants
June 12, 2010, June 12, 2010 17:50, permalink
Actually, I thinking of actually using setTimeout() and clearTimeout().
I also changed the code that tried to collect the arguments, and simply have the caller pass in a script expression as a string and pass that on to setTimeout().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
<html> <head> <script> var Delayer = function(){ var lag = 500; // microsecond of delay var tid = false; this.put = function(callback){ if (tid !== false) clearTimeout(tid); tid = setTimeout(callback, lag); }; }; var delayer = new Delayer; var count = 0; function go(){ count++; delayer.put("window.alert(count)"); } </script> </head> <body> <input type="button" id="go" value="go()" onclick="go();"> </body> </html>
sgrezzeria
June 14, 2010, June 14, 2010 16:01, permalink
My last version.
Insert a dalayer in Function object for an use like this:
whateverFunction.delay(any, arguments,to,pass,at,whateverFunction);
This code pass an extra parameter (as a scope) at setInterval function: IEs do not support extra parameter for setInterval therefore crash in IE because scope is undefined....
Any suggestion?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script> Function.prototype.delayLag = 500; // default microsecond of delay Function.prototype.dalayId = false; Function.prototype.delay = function(){ if (this.dalayId !== false) { clearInterval(this.dalayId); } this.dalayId = setInterval(function(args,scope){ scope.apply(scope, args); clearInterval(scope.dalayId); scope.dalayId = false; }, this.delayLag, arguments,this); return true; }; var count = 0; var recount = 0; var func1 = function(ecc){ alert('go:'+count); }; var func2 = function(ecc){ alert('rec:'+recount); }; func1.delayLag = 500; func2.delayLag = 1000; </script> </head> <body> <input type="button" value='go()' onclick="func1.delay(count++);"> <input type="button" value='rec()' onclick="func2.delay(recount++);"> </body> </html>
sgrezzeria
June 14, 2010, June 14, 2010 16:04, permalink
ok sorry for spam...
pro prevent IE error simply add this workaround code in front of code.
tnx to: http://webreflection.blogspot.com/2007/06/simple-settimeout-setinterval-extra.html
1 2 3 4 5 6
/*@cc_on (function(f){ window.setTimeout =f(window.setTimeout); window.setInterval =f(window.setInterval); })(function(f){return function(c,t){var a=[].slice.call(arguments,2);return f(function(){c.apply(this,a)},t)}}); @*/
This class prevent massive call of a function: execute only the last call of it if not there call for lag microsecond.
--- sorry for my english :(