I have an assignment to write my own throttle function. It needs to pass a certain amount of tests using setTimeout.
This is my code:
var throttle = function(func, delay) {
var counter = 0;
var calledOnce = false;
setInterval(function(){
counter++;
}, 1);
return function() {
if (counter > delay || !calledOnce) {
calledOnce = true;
counter = 0;
return func.apply(this, arguments);
}
};
};
I am testing it with the following:
var callBack = function () {
console.log('called');
};
var func = throttle(callback, 1000);
func(); // should be called
setTimeout(func, 500); // should not be called
setTimeout(func, 1000); // should be called
setTimeout(func, 1500); // should not be called
setTimeout(func, 1900); // should not be called
However, when I run my code just how it is here, the function is only invoked once, with the original func() call, and none of the functions inside of a setTimeout are being invoked.
Is there any obvious problems with my code or testing using setTimeout?
Just because you set it to run at 1ms intervals does not mean, that browser does this. For example if i set it to 0 to force it to take smallest possible interval and do this several times to get average i find it smallest interval i could use is ~6 ms. In case of heavy load this increases significantly.
var start = new Date();
var i = 0, interval = setInterval(function(){
if (++i >= 1000) {
var end = new Date();
var result = (end-start)/1000;
$('#result').text("The average interval was "
+result+" milliseconds");
$('#browser').text(navigator.userAgent);
clearInterval(interval);
}
}, 0);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<p id=result>Please wait about 10 to 20 seconds ...</p>
<p id=browser></p>
It does not count as writing it yourself, but annotated underscore source throttle function :
Returns a function, that, when invoked, will only be triggered at most once during a given window of time. Normally, the throttled function will run as much as it can, without ever going more than once per wait duration; but if you’d like to disable the execution on the leading edge, pass {leading: false}. To disable execution on the trailing edge, ditto.
_.throttle = function(func, wait, options) {
var context, args, result;
var timeout = null;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : _.now();
timeout = null;
result = func.apply(context, args);
if (!timeout) context = args = null;
};
return function() {
var now = _.now();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
result = func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
return result;
};
};
From http://underscorejs.org/#throttle
throttle_.throttle(function, wait, [options])
Creates and returns a new, throttled version of the passed function, that, when invoked repeatedly, will only actually call the original function at most once per every wait milliseconds. Useful for rate-limiting events that occur faster than you can keep up with.
By default, throttle will execute the function as soon as you call it for the first time, and, if you call it again any number of times during the wait period, as soon as that period is over. If you'd like to disable the leading-edge call, pass {leading: false}, and if you'd like to disable the execution on the trailing-edge, pass {trailing: false}.
var throttled = _.throttle(updatePosition, 100);
$(window).scroll(throttled);