Почему цикл Angular Digest не вызывается?

У меня два контроллера и заводской. Я внедряю фабрику и контроллер в главный контроллер, вот фрагменты кода ниже:

Фабрика:

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

  return {
    correct: 0,
    incorrect: 0
  };

});

TallyController, который принимает 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, который принимает TallyFactory и изменяет значение объекта TallyFactory:

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

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

Обратите внимание, что в моем TallyController (второй фрагмент) я добавил наблюдатель в $scope, прослушивающий изменения «счетов».

Когда я запускаю функцию «addTally» из моего MainController с помощью ng-click, она изменяет значение моего объекта Factory (TallyFactory). Поскольку произошли изменения, и я специально создал наблюдателя на своем TallyController ($scope.scores), не следует ли запустить цикл дайджеста и обновить мою консоль с новым значением моего TallyFactory?

Кроме того, мой TallyController НЕ вложен в мой MainController, они отделены друг от друга (не уверен на 100%, имеет ли это значение).

Я не уверен, почему цикл дайджеста не запускается, так как значения TallyFactory изменились.


person HelloWorld    schedule 19.08.2015    source источник
comment
должен работать даже без $watch. Создайте демонстрацию, которая воспроизводит проблему   -  person charlietfl    schedule 20.08.2015
comment
Ты смотришь не то. $scope.$watch('scores.correct', ...   -  person HankScorpio    schedule 20.08.2015
comment
у вас оба контроллера загружены на одну страницу? потому что как ваше приложение загружает TallyController?   -  person Babajide Fowotade    schedule 20.08.2015
comment
Просто чтобы было понятно, что я имел в виду, когда вы говорите, что это изменяет значение моего Factory Object (TallyFactory), что на самом деле неверно. Он изменяет свойство TallyFactory, но сам TallyFactory остается неизменным. Для глубоких часов добавьте true в качестве третьего аргумента часов. $scope.$watch('scores', function(){}, true)   -  person HankScorpio    schedule 20.08.2015
comment
@Claies Комментарий вводит в заблуждение, это правильное использование для factory (хотя value короче). Объект, возвращаемый этой фабрикой, одни и те же при каждом внедрении службы. В противном случае это не будет синглтоном.   -  person Estus Flask    schedule 20.08.2015


Ответы (2)


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

следить за конкретным имуществом. А также

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

наблюдать за всеми из них.

Рассмотрите возможность использования глубокого $watch

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

вместо этого, если свойства scores могут содержать объекты.

По сравнению с глубоким $watch, $watchCollection обеспечивает значительный прирост производительности даже для простых неглубоких объектов. Вот временная шкала профайлера для $watchCollection:

Временная шкала профилировщика $watchCollection

В то время как временная шкала профилировщика deep $watch будет выглядеть следующим образом:

временная шкала глубокого профилировщика $watch

person Estus Flask    schedule 20.08.2015
comment
scores просто указывает на объект, поэтому использование глубокой проверки на равенство решает проблему. Проблема заключается в том, что сам фабричный объект не изменяет только свойства внутри него, но, как вы сказали, если бы это был массив, то watchCollection имеет смысл, и добавление третьего параметра для глубокой проверки равенства true устраняет проблему. - person shaunhusain; 20.08.2015
comment
@shaunhusain $watchCollection — это пример использования для массивов и неглубоких объектов (а scores неглубокий объект). - person Estus Flask; 20.08.2015
comment
о, да, это интересно, только что проверил документы, вы правы, интересно, есть ли какая-либо реальная разница в производительности в проверке watchCollection по сравнению с проверкой deepEquality в обычных часах для мелкого объекта. - person shaunhusain; 20.08.2015
comment
@shaunhusain Я добавил в ответ данные профилировщика. Да, есть очевидная разница в производительности. - person Estus Flask; 02.09.2015
comment
Интересный материал, спасибо, что поделились результатами профилирования - person shaunhusain; 02.09.2015

У меня были некоторые сомнения относительно точной правильности ответа, но после копирования вашего кода во фрагмент, который можно запустить, я только что проверил здесь, что ответ Эстуса приемлем.

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>

person shaunhusain    schedule 20.08.2015