错误:$ rootScope:inprog - 在角度中'不'执行$ apply的正确方法是什么?

时间:2017-03-21 09:40:08

标签: angularjs angularjs-scope angularjs-lifecycle

AngularJS Wiki - Anti-Patterns声明如下:

  

不要if (!$scope.$$phase) $scope.$apply(),这意味着您的$scope.$apply()在调用堆栈中不够高。

我有点理解这一点。有一个内置逻辑,可以确定何时需要执行。当一个外部开发人员没有直接关注不同程序的运行时执行时,确定应该在哪里运行,它会抵消框架。

但我目前正在上传一个大文件,其中上传进度通过进度条显示。我使用的库(resumableJS)又有一个名为fileProgress的事件,在上传进行时调用。如果我在该事件期间什么都不做,那么该栏就没有更新。如果我在其中放置$scope.$apply(),则相应地更新栏,但我得到摘要和/或已经在进行中应用错误。最后,在$$phase检查的帮助下,我得到了两全其美,更新的进度条没有任何错误。

那么在不干扰角度处理顺序的情况下更新我的条形图的正确选择是什么?

2 个答案:

答案 0 :(得分:3)

在您的情况下,当您的摘要周期已经处于阶段时,您正在尝试运行摘要周期。所以它引发了一个错误

您可以使用类似setTimeout(fn,0)的内容。它基本上做的是它立即向队列添加新消息,并在当前正在执行的代码完成时进行处理。

所以在你的角度代码中,你明确地使用$ scope。$ apply(),将它改为下面的代码,它应该可以工作。

$timeout(function(){
   $scope.$apply();
},0)

答案 1 :(得分:1)

错误:$rootScope:inprog行动已在进行中

在任何时间点,只能进行一次$digest$apply操作。这是为了防止很难检测到进入您的应用程序的错误。此错误的堆栈跟踪允许您跟踪当前正在执行的$apply$digest调用的来源,这会导致错误。

常见原因

除了对$apply$digest的错误调用之外,在某些情况下,您可能会因为自己的过错而收到此错误。

API不一致(同步/异步)

在与有时同步且有时异步的API交互时经常会出现此错误。

这不是第三方图书馆的理想设计选择。

要解决此类问题,请将api 修复为始终同步或异步,或强制您的回调处理程序始终使用$timeout服务异步运行。

function MyController($scope, $timeout, thirdPartyComponent) {
  thirdPartyComponent.getData(function(someData) {
    $timeout(function() {
      $scope.someData = someData;
    }, 0);
  });
}

这里我们使用$timeout来安排未来调用堆栈中范围的更改。通过提供0ms的超时时间,这将尽快发生,$timeout将确保在单个$apply块中调用代码。

**仅使用此技术作为最后的手段**。

最好找到错误的来源并进行修复。

有关详细信息,请参阅AngularJS Error Reference - $rootScope/inprog - Diagnosing This Error

另见,