Watching users double-click a form button always makes me cringe. Worse: knowing that AJAX is firing with each click. Instead if flooding our server with AJAX requests it would be nice to limit how frequently the click handler runs. Fortunately, libraries like Underscore.js have wonderful functions like
debounce do just that.
But which do you use?
The documentation for
throttle indicates the passed function will be called at most “once per every wait milliseconds”, whereas
debounce will execute the function on the trailing/leading edge of the wait period. Personally, I find this hard to understand without an example. Check out this jsFiddle that visually explains the difference:
The top set of “lights” uses
throttle. Click on the top example once and watch the first light show up, then really hammer on that mouse button. You’ll see the green lights go on one-by-one, but there will always be at least a 1-second wait between each.
throttle doesn’t stop the click handler from running, rather it’s just limiting it to run once a second. The gotcha: subsequent clicks get rolled into 1 click event that will fire. That leads to the “laggy” second light turning on.
The bottom set of “lights” uses
debounce with a third parameter set to
true so it fires its event on the first click. Try hammering your mouse button again and notice no matter how many times you click the additional lights won’t turn on. Why? Subsequent clicks are filtered out and they reset the wait time. The gotcha: the user still has to wait a whole second for the handler to return to firing events.
Other ways to defeat that secondary click … or not
There are some other ways to defeat a secondary click which can be a bit obtuse:
- jQuery’s one(): If you really only want something to fire once and only once
oneis great. (Underscore.js also has
once.) However, if you still plan on reusing the targeted element you’ll have to rebind your event handler.
- Ignore the built-in
dblclickevent: You could prevent the element’s
dblclick, but the original
clickevent still fires. This doesn’t really work to throttle the clicks.
Other lessons we learned
Through testing we have found that
debounce works really well with a wait time around 500ms.