简体   繁体   中英

Why is the Angular Digest Cycle not being called?

I have two controllers and a factory. I am injecting the factory and a controller into a main controller, here are the code snippets below:

Factory:

app.factory('TallyFactory', function(){

  return {
    correct: 0,
    incorrect: 0
  };

});

TallyController that accepts the TallyFactory:

app.controller('TallyController', function($scope, TallyFactory){    

  $scope.$watch('scores', function(newValue, oldValue){
    console.info('changed!');
    console.log('Old: ' + JSON.stringify(oldValue));
    console.log('New: ' + JSON.stringify(newValue));
  });

  $scope.scores = TallyFactory;
});

MainController which accepts the TallyFactory and changes the value of the TallyFactory Object:

app.controller('MainController', function ($scope,TallyFactory) {

    $scope.addTally = function(){
    TallyFactory.correct++;
  }
});

Notice in my TallyController (second snippet), I added a watcher to the $scope, listening for when "scores" changes.

When I run the "addTally" function from my MainController with an ng-click, it changes the value of my Factory Object (TallyFactory). Since there was a change, and I specifically created a watcher on my TallyController ($scope.scores), shouldn't the digest cycle be triggered and my console update with the new value of my TallyFactory?

Also, my TallyController is NOT nested in my MainController, they are separate from each other (not 100% sure if that matters).

I'm not sure why the Digest Loop isn't triggered since the TallyFactory changed values.

$scope.$watch('scores.correct', function(newValue, oldValue){ ... });

to watch for particular property. And

$scope.$watchCollection('scores', function(newValue, oldValue){ ... });

to watch for all of them.

Consider using deep $watch

$scope.$watch('scores', function(newValue, oldValue){ ... }, true);

instead if scores properties may contain objects.

In comparison with deep $watch , $watchCollection provides significant performance boost even for simple shallow objects. Here is profiler timeline for $watchCollection :

$ watchCollection事件探查器时间轴

While deep $watch profiler timeline will look like this:

$ watch深度分析器时间轴

I had some doubts about the exact correctness of the answer but after copying your code into a snippet that can be run I just verified here that estus' answer is acceptable.

 angular.module('app', []) .controller('TallyController', function($scope, TallyFactory){ $scope.scores = TallyFactory; $scope.$watch('scores', function(newValue, oldValue){ alert('changed!'); console.log('Old: ' + JSON.stringify(oldValue)); console.log('New: ' + JSON.stringify(newValue)); }, true); }) .factory('TallyFactory', function(){ return { correct: 0, incorrect: 0 }; }) .controller('MainController', function ($scope,TallyFactory) { $scope.addTally = function(){ TallyFactory.correct++; } }); 
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script> <div ng-app='app'> <div ng-controller="TallyController"> {{scores}} </div> <div ng-controller="MainController"> <button ng-click="addTally()">Add Tally</button> </div> </div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM