如果我们使用了angularJS中的$scope.$apply()或者$scope.$digest(),我们很可能会遇到类似下面的错误:
Error: [$rootScope:inprog] $apply already in progress
为什么?
因为angularJS框架本身已经在做脏数据检测了,我们没有必要再手动调用$apply或者$digest。
解决
1.angular中的$scope中提供了一个$$phase变量,如果这个变量的值是"$digest" 或者"$apply",就代表angular自身已经在做脏值检测了,不需要我们再去调用$apply或者$digest;否则的话就需要我们手动调用了。
($scope.$$phase || $scope.$root.$$phase) ? '' : $scope.$apply();
$scope.$apply(function() {
$scope.mydata = 'data changed';
});
避免使用以上代码,而用以下代码代替
$timeout(function() {
$scope.mydata = 'data changed';
});
什么时候需要手动调用$apply或者$digest?
1.controller中有异步操作,比如ajax回调,timeout延时等。
可以这么理解:由于异步(延迟)的存在,当开始执行回调函数的时候,angularJS自身controller中的脏值检测已经结束,无法检测到回调函数导致数据的变化。
2.在JQuery代码中修改$scope中的数据。
这种情况是在angular框架之外操作$scope中的数据,angular不能检测到数据变化是正常的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<script src="../src/angular.min.js"></script>
<script src="../src/jquery-3.3.1.min.js"></script>
</head>
<body >
<div id="div1" ng-app="myApp" ng-controller="ctrl1">
<div>{{ text }}</div>
<button id="btn1">Click</button>
</div>
<script>
var app = angular.module('myApp', []);
app.controller('ctrl1', function($scope) {
$scope.text = "value1";
setTimeout(function() {
$scope.text = "value changed after time out";
$scope.$apply();//必需手动进行脏值检测,否则数据无法刷新到界面
},1000);
$(function() {
$("#btn1").click(function() {
$scope.text = "value changed by jquery";
$scope.$apply();
});
})
});
</script>
</body>
</html>
但是代码中最好不要使用$digest、$apply、$$phase这些$scope中的私有的属性或者方法,因为这代表了你没有按照angular的方式来组织代码。比如setTimeout,完全可以用angular中的$timeout代替而不是通过$apply来补救。