Dom*_*ann 91 angularjs angularjs-scope
有时我需要$scope.$apply在我的代码中使用,有时它会抛出"正在进行的摘要"错误.所以我开始找到解决这个问题的方法并找到了这个问题:AngularJS:在调用$ scope时预防错误$ digest.$ apply().但是在评论中(以及角度维基上),您可以阅读:
不要做(!$ scope.$$阶段)$ scope.$ apply(),这意味着你的$ scope.$ apply()在调用堆栈中不够高.
所以现在我有两个问题:
防止"正在进行摘要"错误的另一个"解决方案"似乎是使用$ timeout:
$timeout(function() {
//...
});
Run Code Online (Sandbox Code Playgroud)
这是要走的路吗?它更安全吗?所以这是一个真正的问题:如何完全消除"摘要已经在进行中"错误的可能性?
PS:我只使用$ scope.$ apply适用于非同步的非angularjs回调.(据我所知,你必须使用$ scope.如果你想要应用你的更改,请申请$)
Dom*_*ann 110
经过一番挖掘后,我能够解决使用它是否总是安全的问题$scope.$apply.简短的回答是肯定的.
答案很长:
由于您的浏览器执行Javascript的方式,两个摘要调用不可能偶然发生冲突.
我们编写的JavaScript代码并不是一次性运行,而是依次执行.这些转弯中的每一个都从头到尾不间断地运行,当转弯运行时,我们的浏览器中没有其他任何事情发生.(来自http://jimhoskins.com/2012/12/17/angularjs-and-apply.html)
因此,错误"已经在进行中的摘要"只能在一种情况下发生:当在另一个$ apply内发出$ apply时,例如:
$scope.apply(function() {
// some code...
$scope.apply(function() { ... });
});
Run Code Online (Sandbox Code Playgroud)
如果我们在纯non-angularjs回调中使用$ scope.apply,例如回调函数,就不会出现这种情况.所以下面的代码是100%防弹,没有必要做setTimeoutif (!$scope.$$phase) $scope.$apply()
setTimeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
Run Code Online (Sandbox Code Playgroud)
即使这个是安全的:
$scope.$apply(function () {
setTimeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
});
Run Code Online (Sandbox Code Playgroud)
什么是不是安全的(因为$超时-像所有angularjs助手-已经呼吁$scope.$apply你):
$timeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
Run Code Online (Sandbox Code Playgroud)
这也解释了为什么使用if (!$scope.$$phase) $scope.$apply()反模式.如果$scope.$apply以正确的方式使用,则根本不需要它:例如,在纯js回调中setTimeout.
请阅读http://jimhoskins.com/2012/12/17/angularjs-and-apply.html以获取更详细的说明.
Fla*_*ape 16
现在绝对是一种反模式.即使你检查了$$阶段,我也看到了消化的爆炸.您不应该访问由$$前缀表示的内部API .
你应该用
$scope.$evalAsync();
Run Code Online (Sandbox Code Playgroud)
因为这是Angular ^ 1.4中的首选方法,并且特别是作为应用程序层的API公开.
scope.$apply触发一个$digest循环,这是双向数据绑定的基础
甲$digest的对象周期的检查,即模型(准确地$watch)连接到$scope评估是否它们的值发生了变化,如果检测到的变化那么它采取必要的步骤来更新视图.
现在,当你使用时,$scope.$apply你面临一个错误"已经在进行中",所以很明显$ digest正在运行,但是什么引发了它?
ans - >每次$http通话,全部点击,重复,显示,隐藏等触发一个$digest周期和最糟糕的部分运行每个$ SCOPE.
即说你的页面有4个控制器或指令A,B,C,D
如果$scope每个属性中有4个属性,那么页面上总共有16个$ scope属性.
如果你$scope.$apply在控制器D中触发,那么一个$digest循环将检查所有16个值!加上所有$ rootScope属性.
答案 - >但$scope.$digest触发一个$digest孩子和相同的范围,因此它只会检查4个属性.因此,如果您确定D中的更改不会影响A,B,C,那么请$scope.$diges不要使用$scope.$apply.
因此,$digest即使用户没有触发任何事件,仅仅ng-click或ng-show/hide可能会触发超过100个属性的循环!
在任何情况下,当您的摘要正在进行并且您推送其他服务进行摘要时,它只会给出错误,即摘要已在进行中.所以要治愈这个你有两个选择.您可以检查正在进行的任何其他摘要,如轮询.
第一
if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') {
$scope.$apply();
}
Run Code Online (Sandbox Code Playgroud)
如果上述条件为真,则可以应用$ scope.$ apply otherwies not和
第二个解决方案是使用$ timeout
$timeout(function() {
//...
})
Run Code Online (Sandbox Code Playgroud)
它不会让其他摘要开始直到$ timeout完成它的执行.
| 归档时间: |
|
| 查看次数: |
51855 次 |
| 最近记录: |