Skip to content

Instantly share code, notes, and snippets.

@msssk
Last active May 20, 2022 16:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save msssk/b720a8bddf2ba595347820ac387751ce to your computer and use it in GitHub Desktop.
Save msssk/b720a8bddf2ba595347820ac387751ce to your computer and use it in GitHub Desktop.
Throttle with trailing call preservation
// This is a typical throttle implementation with the difference that it doesn't discard
// the final invocation - instead it runs it at the next valid timeslice.
throttleBoss: function(callback, delay) {
var ready = true,
args = null;
return function throttled() {
var context = this;
if (ready) {
ready = false;
setTimeout(function() {
ready = true;
if (args) {
throttled.apply(context);
}
}, delay);
if (args) {
callback.apply(this, args);
args = null;
} else {
callback.apply(this, arguments);
}
} else {
args = arguments;
}
};
}
@msssk
Copy link
Author

msssk commented Apr 14, 2016

Comparison with Dojo's throttleAfter:

throttleDebounce: final invocation executes at soonest valid timeslice
01234512345123
0    5    5    3

throttleAfter: final invocation is discarded
01234512345123
0    5    5

@kfranqueiro
Copy link

Your comment isn't entirely correct - throttleAfter would not fire at 0.

Unless I'm missing something, I don't see how this changes timing other than that whatsoever (which your comment also seems to suggest). This is basically throttle plus throttleAfter in behavior. The main differences between this and throttleAfter are:

  1. This will call the function immediately upon first invocation - including if that's the only invocation (whereas throttleAfter would still wait the full interval).
  2. This properly passes the last invocation's arguments to the final delayed call. throttleAfter should probably do that but doesn't, I think I'd consider that a bug.

I think we would need a better name for this (and I don't think my suggestion of throttleSandwich will stick, either), and I have to wonder if it can be simplified at all.

@msssk
Copy link
Author

msssk commented Apr 14, 2016

One significant issue with this implementation is that it won't work for throttled functions that receive no arguments.

With an implementation that fixes this issue, my vote is we simply call it throttle. Is there reason to have both this implementation and the existing throttle implementation?

@msssk
Copy link
Author

msssk commented Apr 15, 2016

Goal: a throttle method for rapid event handlers, such as mousemove and scroll.

Presumed desirable traits:

  1. Responsive: execute the first invocation without delay; execute other eligible invocations with minimal delay
  2. Accurate: ensure that trailing invocations during the timeout period are not discarded when the event ceases to be triggered
  3. Performant: of course, throttling should happen for performance, also the manner of throttling should incur minimal overhead

throttle

Trailing invocations are discarded

01234512345123
0    5    5

throttleAfter

Initial invocation and trailing invocations are discarded

1234512345123
    5    5

throttleBoss

Final trailing invocation executes at next eligibile timeslice

01234512345123
0    5    5    3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment