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

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

错误:$digest已在进行中

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


当前回答

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

其他回答

首先,不要这样解决

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

它没有意义,因为$phase只是$digest循环的布尔标志,所以$apply()有时无法运行。记住这是一种糟糕的做法。

而是使用$timeout

    $timeout(function(){ 
  // Any code in here will automatically have an $scope.apply() run afterwards 
$scope.myvar = newValue; 
  // And it just works! 
});

如果使用下划线或lodash,可以使用defer():

_.defer(function(){ 
  $scope.$apply(); 
});

您也可以使用evalAsync。它将在摘要完成后的某个时间运行!

scope.evalAsync(function(scope){
    //use the scope...
});

您应该根据上下文使用$evalAsync或$timeout。

这是一个有很好解释的链接:

http://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm

保持此过程干燥的简便小助手方法:

function safeApply(scope, fn) {
    (scope.$$phase || scope.$root.$$phase) ? fn() : scope.$apply(fn);
}

我一直在使用这种方法,它似乎工作得很好。这只是等待循环完成的时间,然后触发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);
  }
}