AngularJS Debounce Service
HTML
<div ng-app='MyApp' ng-controller="MyCtrl">
<input type="text" debounce-delay="1000" debounce-model="search"></input>
<p>{{ val }}</p>
</div>
JavaScript
angular.module('MyApp', [])
.controller('MyCtrl', ['$scope', '$debounce', function($scope, $debounce) {
$scope.val = 0;
$scope.search = "";
$scope.$watch('search', function (newVal, oldVal) {
if(newVal === oldVal){
return;
}
// called when something in the settings has changed (recursively)
$scope.val++;
});
}])
// http://unscriptable.com/2009/03/20/debouncing-javascript-methods/
// adapted from angular's $timeout code
.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];
...