AngularJS $ watch vs $ watchCollection: which is better for performance?

To view the $scope.$watch variable of a $scope.$watch objectEquality with objectEquality set to true OR $scope.$watchCollection better?

For a $scope object variable (e.g. 15 attributes, some nested 2 levels in depth) updated with input elements and ng-model in the view, how bad is $scope.$watch with objectEquality set to true ? Is this a big thing to avoid?

Is $watchCollection best solution?

I am looking for easy wins to improve the performance of my AngularJS application (I still adhere to v1.2.2).

  // ctrl scope var $scope.filters = { name: '', info: {test: '', foo: '', bar: ''}, yep: '' // etc ... } // ctrl watch ? $scope.$watch('filters', function(newVal, oldVal) { if(newVal !== oldVal) { // call with updated filters } }, true); // or ctrl watch collection ? $scope.$watchCollection('filters', function(newVal, oldVal) { if(newVal !== oldVal) { // call with updated filters } }); // view input with ng-model <input type="text" ng-model="filters.name" /> <input type="text" ng-model="filters.info.test" /> <input type="text" ng-model="filters.yep" /> // etc ... 
+32
angularjs angularjs-scope angularjs-watch
Oct 23 '14 at 19:00
source share
3 answers

The $watchCollection() function is a kind of intermediate between the two $watch() configurations above. It is deeper than the vanilla function $ watch (); but it’s not as expensive as the deep equality function $watch() . Like the $watch() function, $watchCollection() works by comparing references to physical objects; however, unlike the $ watch () function, $watchCollection() goes a single-level depth and performs an additional, shallow control check of the top-level elements in the collection.

see this explanation

+32
Oct 23 '14 at 19:06
source share

$ watch () will run with:

 $scope.myArray = []; $scope.myArray = null; $scope.myArray = someOtherArray; 

$ watchCollection () will be called by everyone above AND:

 $scope.myArray.push({}); // add element $scope.myArray.splice(0, 1); // remove element $scope.myArray[0] = {}; // assign index to different value 

$ watch (..., true) will be run EVERYTHING above AND:

 $scope.myArray[0].someProperty = "someValue"; 

ONLY ONE MORE ...

$ watch () is the only one that fires when the array is replaced by another with the same exact content. For example:

 $scope.myArray = ["Apples", "Bananas", "Orange" ]; var newArray = []; newArray.push("Apples"); newArray.push("Bananas"); newArray.push("Orange"); $scope.myArray = newArray; 

The following is a link to a JSFiddle example that uses all the different clock combinations and displays log messages to indicate which "clock" has been called:

http://jsfiddle.net/luisperezphd/2zj9k872/

+147
Mar 21 '15 at 23:30
source share

$watchCollection optimized for arrays [] vector where elements can be push

and $watch are good for associative array objects {}

$watchCollection will not keep track of depth changes, like a watch with objectEquality set to false.

If you already know the depth structure, you can optimize it as follows:

  // ctrl watch ? $scope.$watch('filters', function(newVal, oldVal) { if(newVal !== oldVal) { // call with updated filters } }); // ctrl watch ? $scope.$watch('filters.info', function(newVal, oldVal) { if(newVal !== oldVal) { // call with updated filters } }); 
+2
Dec 03 '14 at 9:49
source share



All Articles