简体   繁体   中英

Javascript: How do I tweak my debounce function to take an IF conditional?

I found a bug, and tracked it down.
You can see a simplified example of my code here .

As it turns out, I need to debounce my if() statement rather than debouncing the function itself.
I'd like to keep the debounce as a standalone function, but I'm not sure then how to pass the conditional in.

Any pointers?

Here's the code:

var foo = function(xyz) {
    alert(xyz);
};

function setter(func, arg1, arg2) {
    return {
        fn: func,
        arg1: arg1,
        arg2: arg2
    };
}

function debounce(someObject) {
    var duration = someObject.arg2 || 100;
    var timer;
    if (timer) {
        clearTimeout(timer);
    }
    timer = setTimeout(function() {
        someObject.fn(someObject.arg1);
        timer = 0;
    }, duration);
}

var toggle = true;

if (toggle) {
    debounce(setter(foo, 'The best things in life are worth waiting for.', 1250));
} else {
    foo('Instant gratification is sweet!!');
}

Using your example, why not pass toggle in as arg 1... something like:

var toggle = true;
var debouncedFunk = function(toggle) {
  if (toggle)
    // the function call
  else
    // something else
};
debounce(debouncedFunk, toggle, 1250);

You should also look into using the Function objects .call and .apply methods. They are for calling the function and passing in arguments. Taking the example function:

var example = function(one, two) { 
  // Logic here
};

You can call it in three ways:

// First
example(1, 2);
// Second
example.call({}, 1, 2);
// Third
example.apply({}, [ 1, 2 ]);

The first is the standard way to call a function. The difference between the first and the .call is that the first parameter to .call is the context object of the function (what this will point to inside the function), the other parameters are passed after that (and a known list is required for .call . The benefit of .apply is that you can pass an array to the function of arguments and they will be assigned to the parameter list appropriately, the first parameter is still the context object.

It would simplify your debounce function, instead of having to deal with a structured object as you currently do.

A suggestion for your debounce:

var debounce = function(funk, delay) {
  var args = [];
  if (arguments.length > 2)
    args = [].slice.call(arguments, 2);
  setTimeout(function() { funk.apply({}, args); }, delay);
};

Changing your current if to:

var toggle = true;
var debouncedFunk = function(toggle) {
  if (toggle)
    // Do if true
  else
    // DO if false
};
debounce(debouncedFunk, 1000, toggle);

Maybe too much information (sorry)?

As a last note, I'd recommend using a framework (if possible) where these functions have been implemented already (and many other useful functions) such as Underscore . Using Underscore your example would look like:

// Define debouncedFunk and toggle
debouncedFunk = _.bind(debouncedFunk, {}, toggle);
debouncedFunk = _.debounce(debouncedFunk, 1000);
debouncedFunk();

EDIT

Fixed the underscore example, _.debounce returns a function that will execute only after the delay but it still needs to be called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM