Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

For watching an object scope variable, is $scope.$watch with objectEquality set to true OR $scope.$watchCollection better?

For a $scope object variable (like 15 attributes, some nested 2 levels deep) 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 a better solution?

I am looking for easy wins to improve performance on my AngularJS App (I'm still stuck on 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 ...   
like image 593
user12121234 Avatar asked Oct 23 '14 19:10

user12121234


People also ask

What is the use of $Watch in Angularjs?

$watch() function is used to watch the changes of variables in $scope object. Generally the $watch() function will create internally in Angularjs to handle variable changes in application.

What is $watchCollection?

$watch() is used to watch changes, for example in some input fields. This function always returns old value and new value. $watchCollection() is used when trying to push something to a collection, or when removing some elements from it. This function returns previous collection and new collection.


2 Answers

$watch() will be triggered by:

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

$watchCollection() will be triggered by everything 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 triggered by EVERYTHING above AND:

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

JUST ONE MORE THING...

$watch() is the only one that fires when an array is replaced with 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; 

Below is a link to an example JSFiddle that uses all the different watch combinations and outputs log messages to indicate which "watches" were triggered:

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

like image 67
Luis Perez Avatar answered Sep 22 '22 07:09

Luis Perez


The $watchCollection() function is a sort-of mid-ground between the two $watch() configurations above. It's more in-depth than the vanilla $watch() function; but, it's not nearly as expensive as the deep-equality $watch() function. Like the $watch() function, the $watchCollection() works by comparing physical object references; however, unlike the $watch() function, the $watchCollection() goes one-level deep and performs an additional, shallow reference check of the top level items in the collection.

see this explanation

like image 29
Narek Mamikonyan Avatar answered Sep 24 '22 07:09

Narek Mamikonyan