angular中的$scope中提供了一个$$phase变量,如果这个变量的值是"$digest" 或者"$apply",就代表angular自身已经在做脏值检测了,不需要我们再去调用$apply或者$digest;否则的话就需要我们手动调用$apply或者$digest了。利用这个属性,我们就可以方便解决上面的错误了,判断一下呗。下面是一个工具函数,好理解吧。
function safeApply(scope, fn) { (scope. phase||scope.$root. phase) ? fn() : scope.$apply(fn); }
最后提一下,$digest、$apply、$$phase这些属性或者方法其实都是$scope中的私有的,最好不要使用。如果你用到了这些方法,基本可以断言你的代码存在问题,没有按照angular的方式来组织代码。比如情况1中的setTimeout,完全可以用angular中的$timeout代替,这才是推荐的方式,而不是通过$apply来补救。
<html> <head> <script src="https://www.jb51.net/jquery-1.11.1.min.js"></script> <script src="https://www.jb51.net/angular.js"></script> <script> var myModule = angular.module('myModule', []); myModule.controller("ctrl_1",function($scope, $timeout){ $scope.text = "place"; $timeout(function(){ $scope.text = "value setted after time out"; },1000); }); $(function(){ angular.bootstrap($("#div1")[0], ["myModule"]); }) </script> </head> <body> <div ng-controller="ctrl_1"> <div>{{text}}</div> <input type="button" value="jquery-event"></input> </div> </body> </html>
所以解决“$apply already in progress”最好的方式,就是不要使用$scope.$apply()或者$scope.$digest()。