我发现自从在angular中构建应用程序以来,我越来越需要手动将页面更新到我的范围。

我知道的唯一方法是从控制器和指令的范围调用$apply()。这样做的问题是,它不断向控制台抛出一个错误,错误如下:

错误:$digest已在进行中

有人知道如何避免这种错误或以不同的方式实现相同的事情吗?


当前回答

如果你这样做,有时你仍然会出错(https://stackoverflow.com/a/12859093/801426).

试试看:

if(! $rootScope.$root.$$phase) {
...

其他回答

我建议您使用自定义事件,而不是触发摘要循环。

我发现,广播自定义事件并为此事件注册侦听器是一个很好的解决方案,无论您是否处于摘要周期,都可以触发您希望发生的操作。

通过创建自定义事件,您的代码也会更高效,因为您只触发订阅所述事件的侦听器,而不会像调用作用域时那样触发绑定到作用域的所有监视$申请

$scope.$on('customEventName', function (optionalCustomEventArguments) {
   //TODO: Respond to event
});


$scope.$broadcast('customEventName', optionalCustomEventArguments);

在为我们创建一个可重用的$safeApply函数方面,yearmomo做得很好:

https://github.com/yearofmoo/AngularJS-Scope.SafeApply

用法:

//use by itself
$scope.$safeApply();

//tell it which scope to update
$scope.$safeApply($scope);
$scope.$safeApply($anotherScope);

//pass in an update function that gets called when the digest is going on...
$scope.$safeApply(function() {

});

//pass in both a scope and a function
$scope.$safeApply($anotherScope,function() {

});

//call it on the rootScope
$rootScope.$safeApply();
$rootScope.$safeApply($rootScope);
$rootScope.$safeApply($scope);
$rootScope.$safeApply($scope, fn);
$rootScope.$safeApply(fn);

当我们要求angular运行摘要循环时,问题基本上就要出现了,尽管它正在进行中,这对angular的理解造成了问题。控制台中的结果异常。1.调用范围没有任何意义$$timeout函数中的apply(),因为在内部它也会这样做。2.该代码使用普通JavaScript函数,因为它的本机非角度定义,即setTimeout3.要做到这一点,你可以利用if(!scope.$$phase){范围$evalAsync(函数){});}

当我禁用调试器时,错误不再发生。在我的例子中,这是因为调试器停止了代码执行。

我一直在使用这种方法,它似乎工作得很好。这只是等待循环完成的时间,然后触发apply()。只需从任意位置调用函数apply(<yourscope>)。

function apply(scope) {
  if (!scope.$$phase && !scope.$root.$$phase) {
    scope.$apply();
    console.log("Scope Apply Done !!");
  } 
  else {
    console.log("Scheduling Apply after 200ms digest cycle already in progress");
    setTimeout(function() {
        apply(scope)
    }, 200);
  }
}