diff --git a/scripts/tests/throttle-test.js b/scripts/tests/throttle-test.js new file mode 100644 index 000000000..e84fc4a8a --- /dev/null +++ b/scripts/tests/throttle-test.js @@ -0,0 +1,34 @@ +var Util = require("../../lib/common-util"); + +(function (throttle) { + var last = 0; + var last_call = 0; + var f = Util.throttle(function (boop) { + var now = +new Date(); + if (last) { + console.log("last execution was %sms ago", now - last); + } else { + console.log("this is the first execution"); + } + last = now; + + //console.log('time of execution:', now); + console.log(boop); + }, 1000); + + [150, 250, 580, 850, 1500, 2200, 3990, 5000].forEach(function (delay) { + setTimeout(function () { + var now = +new Date(); + + if (last_call) { + console.log("last call was %sms ago", now - last_call); + } + + last_call = now; + //console.log("time of call for delay(%s):", delay, now); + f(delay); + }, delay); + }); +}(Util.throttle2)); + + diff --git a/www/common/common-util.js b/www/common/common-util.js index 0e86ecc8c..41797e7c8 100644 --- a/www/common/common-util.js +++ b/www/common/common-util.js @@ -306,11 +306,43 @@ }; Util.throttle = function (f, ms) { + var last = 0; var to; + var args; + + var defer = function (delay) { + // no timeout: run function `f` in `ms` milliseconds + // unless `g` is called again in the meantime + to = setTimeout(function () { + // wipe the current timeout handler + to = undefined; + + // take the current time + var now = +new Date(); + // compute time passed since `last` + var diff = now - last; + if (diff < ms) { + // don't run `f` if `g` was called since this timeout was set + // instead calculate how much further in the future your next + // timeout should be scheduled + return void defer(ms - diff); + } + + // else run `f` with the most recently supplied arguments + f.apply(null, args); + }, delay); + }; + var g = function () { - clearTimeout(to); - to = setTimeout(Util.bake(f, Util.slice(arguments)), ms); + // every time you call this function store the time + last = +new Date(); + // remember what arguments were passed + args = Util.slice(arguments); + // if there is a pending timeout then do nothing + if (to) { return; } + defer(ms); }; + g.clear = function () { clearTimeout(to); to = undefined;