5

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));

}());
Stan Quinn
  • 473
  • 5
  • 12
  • You don't make it easy to determine the difference between the two. – Gabs00 Aug 21 '14 at 04:43
  • the difference would be between throttling foo() and throttling foo(x) – Stan Quinn Aug 21 '14 at 05:18
  • That doesn't really describe the behavior you are looking for.Do you want to keep the initial value of x? Do you want a different x everytime. Not to mention you posted a lot of code, with very subtle changes. If not for the addEventListener line I would not have guessed what you wanted. But it was still a guess. – Gabs00 Aug 21 '14 at 05:28
  • foo(x) should operate like any other javascript function...keep in mind what throttling is for...I have a function that's called a lot...I'd like it to not be called as much....first call is immediate, second call is only after some time period that gets passed in, and third call also is only after some time period, etc. Now I'm not trying to change how my function works...I want it to work the same before throttling as it does after throttling is implemented. The point of throttling is of course to give up the thread and let other stuff happen before the function is called again. – Stan Quinn Aug 21 '14 at 05:43

1 Answers1

14

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])

Gabs00
  • 1,869
  • 1
  • 13
  • 12
  • I tried wrapping foo(x) in an anonymous function before passing it in, which didn't work, but I'll check out your example with the foo wrapper to see if it works before I mark it as answered... – Stan Quinn Aug 21 '14 at 18:48
  • @StanQuinn How did it go for you? – Gabs00 Aug 21 '14 at 21:10
  • Thank you for this answer! `throttle(foo, 2000, [5])` works as expected, but the Lodash docs do not reflect this... – The Nomad Jun 09 '20 at 00:00