Бесконечный цикл с привязкой выражения Angular
У меня есть приложение angular, которое отображает значение, возвращаемое методом контроллера, посредством простого привязки выражения:
<div>{{getValue()}}</div>
Если рассматриваемый метод просто возвращает значение, метод вызывается дважды, и это довольно странно:
$scope.getValue = function(){
return 'some value';
}
Но если метод выполняет некоторую асинхронную работу, такую как получение файла с сервера, код переходит в бесконечный цикл:
$scope.getValueAsync = function(){
$http.get('myfile.html')
.success(function (data, status, headers, config) {
return 'some async value';
});
return 'file not found'; // same value returned every time but $digest cycle still loops
}
Я новичок в angular, поэтому, возможно, пропустил что-то основное здесь, но может кто-нибудь объяснить, что происходит?
Plunker
Здесь плукер, чтобы играть с http://plnkr.co/7BriYDbdVJvIoIigQcTU
Ответы
Ответ 1
Несмотря на то, что ваша функция async возвращает ту же самую точную строку каждый раз, цикл $digest запускается в циклах, потому что ваша функция также делает вызов ajax с помощью службы $http.
$http триггеров службы $rootScope.$apply()
когда запросы завершены, и поскольку $apply
запускает цикл $digest, это делает ваше выражение выражения переопределенная, которая в свою очередь заставляет вашу функцию асинхронного вызова снова называться и так далее...
app.controller('MainCtrl', function($scope, $http) {
$scope.getValue = function(){
return 'some value';
}
$scope.getValueAsync = function(){
$http.get('myfile.html')
.success(function (data, status, headers, config) {
return 'some async value';
});
return 'file not found';
}
});
<div>{{getValueAsync()}}</div>
Мораль истории. Если вы используете функции в выражениях, убедитесь, что ваши функции не влияют на что-то вне их, которое вызовет цикл $digest, и убедитесь, что ваши функции всегда возвращают такой же выход, учитывая тот же ввод.
Ответ 2
Я встретил ту же проблему, что и вы, чтобы исправить проблему, мы можем кэшировать результаты функции. Для этой цели я предпочитаю использовать функцию memoize Lo-Dash. Я создаю демоверсию, чтобы показать вам, как мне удалось исправить эту проблему. The following link contains the demo:
http://plnkr.co/edit/KBmk4J2ZCt0SsmZlnKZi?p=preview