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

1

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

}());
Lawrenson answered 21/8, 2014 at 4:17 Comment(4)
You don't make it easy to determine the difference between the two.Amylose
the difference would be between throttling foo() and throttling foo(x)Lawrenson
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.Amylose
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.Lawrenson
A
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])

Amylose answered 21/8, 2014 at 5:22 Comment(3)
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...Lawrenson
@StanQuinn How did it go for you?Amylose
Thank you for this answer! throttle(foo, 2000, [5]) works as expected, but the Lodash docs do not reflect this...Livingston

© 2022 - 2024 — McMap. All rights reserved.