Error: $rootScope:inprog -- What is the correct way to 'not' execute $apply in angular?

Error: $rootScope:inprog -- What is the correct way to 'not' execute $apply in angular?

AngularJS Wiki - Anti-Patterns 声明如下:

Don't do if (!$scope.$$phase) $scope.$apply(), it means your $scope.$apply() isn't high enough in the call stack.

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

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

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

在您的情况下,您正在尝试 运行 摘要周期,而摘要周期已经进入阶段。所以它抛出一个错误

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

因此,在您的 angular 代码中,您明确执行 $scope.$apply() 的地方,将其更改为下面的代码,它应该可以工作。

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

错误:$rootScope:inprog 操作已在进行中

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

常见原因

除了对 $apply$digest 的简单错误调用之外,在某些情况下,您可能会遇到此错误,这并非您自己的过错。

不一致API (Sync/Async)

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

这不是第 3 方库的理想设计选择。

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

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

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

** 仅在万不得已时才使用此技术**。

最好找到错误的根源并修复。

有关详细信息,请参阅 AngularJS 错误参考 - $rootScope/inprog - 诊断此错误

另见,