初学angular的时候,咱们在使用中常常遇到更改scope里的值,可是model没有相应的更新。因而咱们发现angular有一个$apply()方法,来update咱们的model.可是咱们使用事后,有时候控制台会报出错误:html
Error: $digest / $apply already in progress。angularjs
而后咱们百度获得的解决方案是:express
if(!$scope.$$phase) { //$digest or $apply }
一直一来,我在我初学angular后作的项目里也是这么干的。直到某一天我看到了有人说:
app
而后我开始反思,个人程序是是否是哪里写的有问题?在我翻看了不少大神的文章后,我大体理解了。函数
为何咱们会使用到$apply()?oop
通常状况,咱们在 controller初始化、使用$http的callbacks、相似ng-click这类的ng-*事件时,angular都会用$apply()包起来当里面的function或者一个Angular expression string执行后,就会去调用$scope.$digest()更新数据的绑定。因此是不须要你去主动调用$apply()的,且你在$apply()里面调用$apply()将会抛错的。就是如大家看到的$digest / $apply already in progress。spa
若是咱们用到了$apply()那么应该是如下状况:code
a. 代码处于$digest loop(更新周期)外,好比在"link"指令(directive)响应函数内部使用。也就是说,只能在$controller以外调用$apply,这样它就能够访问到HTML或其余控制器的声明代码 - 好比apply调用link指令并触发相应功能,这时侯是确定在$digest loop以外的。htm
b. 在你的代码块里面还包含有新的函数块,好比:事件
function Ctrl($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.message = "Timeout called!"; // AngularJS unaware of update to $scope }, 2000); }
message在内部匿名函数内被赋值,是没法触发angular的脏值检测的,正确的作法就是:
function Ctrl($scope) { $scope.message = "Waiting 2000ms for update"; setTimeout(function () { $scope.$apply(function () { $scope.message = "Timeout called!"; }); }, 2000); }
如何正确使用$apply()?
$scope.$apply()接收一个函数或Angular表达式字符串,并执行它,而后调用 $scope.$digest()来更新全部绑定或侦听者。
但有些人的作法是像我最初同样,直接使用
if(!$scope.$$phase) { //$digest or $apply }
这个作法就会致使若是你的代码出错,而后又没有相应的处理机制那么程序就会卡死在那里。
$apply不只仅执行你的代码,它内部的try / catch语句让你的错误老是能被捕捉到,而且$digist是最后的保障,它意为着即便一个错误抛出,它仍能运行。因此正确的作法是:
$scope.$apply(function () { $scope.message = "Timeout called!"; });
以上是我观点,若有错误,请指证!