Stan Quinn
Stan Quinn

Reputation: 503

Is it possible to create a throttle function that can take in as parameters another function (that also has parameters), and the time delay

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

Answers (1)

Gabs00
Gabs00

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

Related Questions