huguangju / wiki

A curated list of awesome lists of JavaScript, CSS and Nodejs on Github
74 stars 32 forks source link

避免调用$scope.$apply()时发生$digest already in progress错误 #6

Open huguangju opened 9 years ago

huguangju commented 9 years ago

在使用Angular的时候避免不了经常手动更新作用域的情况,特别是在指令中。通常是用 controller 和 directives 的 $apply() 来手动触发 $digest 的。不过直接用它的话,有一定机率会在控制台抛出错误:

Error: $digest already in progress

很多第三方指令中,包括 ui-event 都是这样写来避免报错的:

if (!$scope.$$phase) {
  $scope.$apply();
}

$$phase 是一个标志,是否angular 在 $digest 循环中。如果 $digest 循环中 ,$scope.$$phase 会返回true。

但是官方不建议我们这么做 When-to-use-$scope.$apply():

Do NOT randomly sprinkle it throughout your code. If you are doing if (!$scope.$$phase) $scope.$apply() it's because you are not high enough in the call stack.

最好不要用 $$phase

正确的方式是:

$timeout(function() {
  // anything you want can go here and will safely be run on the next digest.
})

或者

$scope.$evalAsync(function(){
  // ....
}) 

你应该知道的一些细节:

参考:

  1. AngularJS : Prevent error $digest already in progress when calling $scope.$apply()
  2. Why is using if(!$scope.$$phase) $scope.$apply() an anti-pattern?
  3. What is $$phase in AngularJS?
HiKWang commented 7 years ago

解决了实际的问题,非常有用,感谢分享!