AngularJS $watch with debounce

When you want to use $scope.$watch to monitor changes to a variable in AngularJS you may not want to execute the watch on every scope change, so you need to use debounce. A debounce function limits the rate at which a function can fire.

You can use Underscore.js but you may not want to include the underscore library in your app in which case below is a angular version of debounce.

//angularjs debounce
app.factory('debounce', function($timeout) {
    return function(callback, interval) {
        var timeout = null;
        return function() {
            $timeout.cancel(timeout);
            timeout = $timeout(function () { 
                callback.apply(this, args); 
            }, interval);
        };
    }; 
});

All you do is wrap the $watch listener in the debounce. The usage for $scope.$watch is:

$watch(watchExpression, listener, [objectEquality]);

In the below example you want to watch the products array for changes and increment a counter with a debounce of 1 second. The products data is displayed in a form using ng-repeat.

//define initial values
$scope.products = []; // products array populated with data from a service
$scope.productChanges = 0;
//watch products for changes with 1 second debounce to 
//prevent every keystroke incrementing productChanges
$scope.$watch('products', debounce(function() {
   $scope.productChanges++;
},1000), true);

 

3 thoughts on “AngularJS $watch with debounce”

  1. Thanks for the solution.
    There’s one thing regarding the args variable: it should be arguments and not args.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top