使用$apply执行多操作时出现[$rootScope:inprog]错误,求代码修复方案
这个错误我之前也碰到过!本质原因就是你在Angular的消化周期已经在运行的时候,又手动触发了$scope.$apply(),而且你的代码里还连续调用了两次——哪怕前面有!$scope.$$phase的判断,第二次调用还是会撞进正在进行的周期里。
先说说你代码里的问题
- 你先判断
!$scope.$$phase然后调用了一次$apply,紧接着又直接调用了一次$scope.$apply():第一次$apply已经启动了消化周期,这个周期还没走完,第二次调用自然就会触发冲突错误。 - 额外提一句:
$$phase是Angular的内部私有属性,官方其实不推荐依赖它来判断是否要调用$apply,它可能在后续版本里发生变化。
解决方案:简化你的$apply调用
其实你的场景里,大部分情况下根本不需要手动调用$apply!因为$scope.update是控制器里的方法,本身就在Angular的上下文当中,Angular会自动跟踪$scope.PatternData的变化,触发脏检查和消化周期。
方案1:直接移除多余的$apply
这是最简洁的修改方式:
$scope.update = function () { //更新前移除列表中的空行 if ($scope.PatternData.length > 1) { removeEmptyRow($scope.PatternData); } // 这里不需要手动调用$apply,Angular会自动处理$scope的变化 //更新数据 orderPatternService.updatePattern(function () { //重载数据表 $scope.tableParams.reload(); //显示通知 $timeout(function () { notifyService.popEdit(); }); },$scope.PatternData); };
方案2:如果removeEmptyRow需要强制触发消化周期
如果removeEmptyRow是脱离Angular上下文的操作(比如直接操作数组但没触发Angular的脏检查),那可以把这个修改操作包裹在一次$apply的回调里,既确保Angular跟踪变化,又不会重复触发:
$scope.update = function () { //更新前移除列表中的空行 if ($scope.PatternData.length > 1) { $scope.$apply(function() { removeEmptyRow($scope.PatternData); }); } //更新数据 orderPatternService.updatePattern(function () { $scope.tableParams.reload(); $timeout(function () { notifyService.popEdit(); }); },$scope.PatternData); };
另外,你在异步回调里用$timeout是非常正确的选择——$timeout会自动触发$apply,确保notifyService.popEdit()的操作能被Angular感知到。
内容的提问来源于stack exchange,提问作者Triet Pham
相关产品推荐
相关产品推荐

