Skip to content

Instantly share code, notes, and snippets.

@typeofweb
Created November 28, 2013 09:48
Show Gist options
  • Save typeofweb/7689539 to your computer and use it in GitHub Desktop.
Save typeofweb/7689539 to your computer and use it in GitHub Desktop.
angular.module('ngDebounce', [])
.factory('$debounce', ['$rootScope', '$browser', '$q', '$exceptionHandler',
function($rootScope, $browser, $q, $exceptionHandler) {
var deferreds = {},
methods = {},
uuid = 0;
function debounce(fn, delay, invokeApply) {
var deferred = $q.defer(),
promise = deferred.promise,
skipApply = (angular.isDefined(invokeApply) && !invokeApply),
timeoutId, cleanup,
methodId, bouncing = false;
// check we dont have this method already registered
angular.forEach(methods, function(value, key) {
if(angular.equals(methods[key].fn, fn)) {
bouncing = true;
methodId = key;
}
});
// not bouncing, then register new instance
if(!bouncing) {
methodId = uuid++;
methods[methodId] = {fn: fn};
} else {
// clear the old timeout
deferreds[methods[methodId].timeoutId].reject('bounced');
$browser.defer.cancel(methods[methodId].timeoutId);
}
var debounced = function() {
// actually executing? clean method bank
delete methods[methodId];
try {
deferred.resolve(fn());
} catch(e) {
deferred.reject(e);
$exceptionHandler(e);
}
if (!skipApply) $rootScope.$apply();
};
timeoutId = $browser.defer(debounced, delay);
// track id with method
methods[methodId].timeoutId = timeoutId;
cleanup = function(reason) {
delete deferreds[promise.$$timeoutId];
};
promise.$$timeoutId = timeoutId;
deferreds[timeoutId] = deferred;
promise.then(cleanup, cleanup);
return promise;
}
// similar to angular's $timeout cancel
debounce.cancel = function(promise) {
if (promise && promise.$$timeoutId in deferreds) {
deferreds[promise.$$timeoutId].reject('canceled');
return $browser.defer.cancel(promise.$$timeoutId);
}
return false;
};
return debounce;
}]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment