Skip to content

Instantly share code, notes, and snippets.

@jhickner
Created April 11, 2012 22:05
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jhickner/2363070 to your computer and use it in GitHub Desktop.
Save jhickner/2363070 to your computer and use it in GitHub Desktop.
underscore.js -> clojurescript
(defn debounce [func wait immediate]
(let [timeout (atom nil)]
(fn []
(this-as this
(let [context this
args js/arguments
later (fn []
(reset! timeout nil)
(when-not immediate
(.apply func context args)))]
(if (and immediate (not @timeout))
(.apply func context args))
(js/clearTimeout @timeout)
(reset! timeout (js/setTimeout later wait)))))))
(defn throttle [func wait]
(let [result (atom nil)
throttling (atom nil)
more (atom nil)
timeout (atom nil)
when-done (debounce (fn []
(reset! more false)
(reset! throttling false)) wait)]
(fn []
(this-as this
(let [context this
args js/arguments
later (fn []
(reset! timeout nil)
(when @more (.apply func context args))
(when-done))]
(when-not @timeout
(reset! timeout (js/setTimeout later wait)))
(if @throttling
(reset! more true)
(reset! result (.apply func context args)))
(when-done)
(reset! throttling true)
@result)))))
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time.
_.throttle = function(func, wait) {
var context, args, timeout, throttling, more, result;
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
return function() {
context = this; args = arguments;
var later = function() {
timeout = null;
if (more) func.apply(context, args);
whenDone();
};
if (!timeout) timeout = setTimeout(later, wait);
if (throttling) {
more = true;
} else {
result = func.apply(context, args);
}
whenDone();
throttling = true;
return result;
};
};
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
if (immediate && !timeout) func.apply(context, args);
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
@rodnaph
Copy link

rodnaph commented Apr 23, 2013

Just created a fork with my attempt at a slightly more concise version of debounce (not looked at throttle).

See what you think, not sure if i've lost some functionality...

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