Reputation: 503
So I've already written a function that works (based on underscores throttle) for functions that don't take in a parameter, but I'd like to make it generic enough to pass in a function with a variable number of parameters. Here's what I have:
(function () {
var lastTime = new Date().getTime();
function foo() {
var newTime = new Date().getTime();
var gap = newTime - lastTime; // Travels up scope chain to use parents lastTime. Function has access to variables declared in the same scope
console.log('foo called, gap:' + gap);
lastTime = newTime; // Updates lastTime
//console.log(x);
//x++;
}
var throttle = function(func, wait) {
var result;
var timeout = null; // flag updated through closure
var previous = 0; // time last run updated through closure
return function() { //func, wait, timeout, previous available through scope
var now = new Date().getTime();
var remaining = wait - (now - previous);
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(this, arguments); //func is available through closure
}
return result;
};
};
document.addEventListener("scroll", throttle(foo, 1000));
//document.addEventListener("scroll", throttle(foo(5), 2000));
}());
But I'd like to modify foo to foo(x) and get this to work
(function () {
var lastTime = new Date().getTime();
function foo(x) {
var newTime = new Date().getTime();
var gap = newTime - lastTime; // Travels up scope chain to use parents lastTime. Function has access to variables declared in the same scope
console.log('foo called, gap:' + gap);
lastTime = newTime; // Updates lastTime
console.log(x);
x++;
}
var throttle = function(func, wait) {
var result;
var timeout = null; // flag updated through closure
var previous = 0; // time last run updated through closure
return function() { //func, wait, timeout, previous available through scope
var now = new Date().getTime();
var remaining = wait - (now - previous);
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = func.apply(this, arguments); //func is available through closure
}
return result;
};
};
document.addEventListener("scroll", throttle(foo(5), 2000));
}());
Upvotes: 5
Views: 6225
Reputation: 1877
throttle(foo(5), 2000)
Will not work because when you call a function with the parenthesis, you are invoking the function.
You would need to wrap foo
in an anonymous function when passing it to throttle.
throttle(function(){
foo(5)
}, 2000)
If you wanted to keep track of the original value of x
. wrap foo in a function and return foo. trapping the value in closure scope.
function foo(x) {
return function(){
var newTime = new Date().getTime();
var gap = newTime - lastTime; // Travels up scope chain to use parents lastTime. Function has access to variables declared in the same scope
console.log('foo called, gap:' + gap);
lastTime = newTime; // Updates lastTime
console.log(x);
x++;
}
}
Then you actually can us throttle(foo(5), 2000)
because it does not execute the intended function on the first call.
Example here: http://repl.it/XOj/5 (fixed example)
A solution that takes in any number of args, modifies throttle:
function throttle(func, wait, args){
//do throttle stuff
func.apply(null, args);
}
Then throttle(foo(5), 2000)
becomes throttle(foo, 2000, [5])
Upvotes: 14