New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Suggestion: _.debounce and _.throttle take extra parameter for how to combine arguments #310
Comments
Commenting on my own suggestion, the call to combine() should specify the same context as the payload function, hence
in case the arguments need to access the context object.... |
Should now be fixed on master. |
I think your close comment applies to another issue (probably #170), as the issue raised by this request still applies on master. |
Ah, you're right. Accumulating arguments is outside of the scope of Underscore -- feel free to stash your accumulated data in a good place external to the |
That's a pity, I consider debounce to be a sort of fold-left (reduce) over multiple calls with timeout hence the accumulator... but it's your call :) |
OK, not to keep banging on, but in case anyone's looking at this sometime later and wondering how to do the same, I figured this was about the cleanest way without modifying debounce itself (I add it to the _ object, others may prefer not to)
This gives a debounced function that has its arguments reduced by the combine function so, for example,
will a few second later call console.log with the array [3,4,7,8,9] |
@schmerg — this looks tremendously useful. Would you be willing to license that code under the MIT license? (A "yes" will suffice!) |
@markjaquith Sure thing - yes. Glad to... |
If anyone comes along and wants updated/commented modern js version of the above: _.mixin({
debounceReduce(func, wait, combine) {
let allArgs; // accumulator for args across calls
// normally-debounced fn that we will call later with the accumulated args
const wrapper = _.debounce(() => func(allArgs), wait);
// what we actually return is this function which will really just add the new args to
// allArgs using the combine fn
return (...args) => {
allArgs = combine(allArgs, [...args]);
wrapper();
};
},
}); |
@kmannislands Hey, your version doesn't reset Shouldn't it be: const wrapper = _.debounce(() => {
const args = allArgs;
allArgs = undefined;
func(args);
}, wait); |
@markjaquith +1 Also |
If I use _.debounce() to make a debounced function and then call it 3 times in succession with 3 different sets of arguments, then (as of v1.1.7) the wrapped payload function will finally be called with the arguments specified by the 3rd call - that is the first and second arguments are discarded.
While this is often valid (and what key debouncing typically does, hence a reasonable default) I find myself wanting to use debounce to accumulate arguments, for example I have an AJAX call that can get multiple keys at once, so I use debounce to buffer up keys for a second and then issue a combined request.
My suggestion is therefore that debounce takes an optional 3rd "combine" argument that will be called with 2 args,
and returns the new list of accumulated args. When the payload function is called, the accumulated list of args is cleared.
If no value is passed for the combine parameter, the default combine preserves existing behaviour
function(acc, newargs) { return newargs; }
but you can also decide to use the first set of arguments
function(acc, newargs) { return acc || newargs; }
or what I want to do which is simply append all the arguments
function(acc,newargs) { return (acc || []).concat(newargs); }
and of course others may want to do something fancier
This would require the following change to the internal limit function
and then a change to debounce to accept and pass thru the new argument with default value if not specified.
The corresponding throttle function currently uses the first set of arguments alone (throttle effectively ignores calls happening within wait milliseconds of a first call and uses the first call set of args, debounce effectively ignores all but the last call in a sequence occurring within the wait period of each other), so I'd suggest the below to again preserve the current default behaviour
This would seem the easiest and most general way to achieve this functionality without excessive wrappers to maintain the argument lists, but I'd be interested to know if there's an easy way to achieve this without changing underscore.
The text was updated successfully, but these errors were encountered: