为什么使用if(!$范围。$$阶段)$范围。$适用()的反模式? [英] Why is using if(!$scope.$$phase) $scope.$apply() an anti-pattern?
问题描述
有时候,我需要使用 $范围。$适用
在我的code,有时它抛出一个已经消化进步的错误。于是我开始寻找解决的办法,发现这个问题:<一href=\"http://stackoverflow.com/questions/12729122/$p$pvent-error-digest-already-in-progress-when-calling-scope-apply\">$p$pvent错误$摘要已经调用$范围时进行。$适用()。然而,在注释(和角维基)你可以阅读:
Sometimes I need to use $scope.$apply
in my code and sometimes it throws a "digest already in progress" error. So I started to find a way around this and found this question: Prevent error $digest already in progress when calling $scope.$apply(). However in the comments (and on the angular wiki) you can read:
不要做,如果(!$范围。$$阶段)$范围。$适用(),这意味着你的$范围。$适用()不是调用堆栈不够高。
Don't do if (!$scope.$$phase) $scope.$apply(), it means your $scope.$apply() isn't high enough in the call stack.
所以,现在我有两个问题:
1.究竟为什么这是一个反模式?
2.如何安全地使用$范围。$申请?
So now i have two questions: 1. Why exactly is this an anti-pattern? 2. How can i safely use $scope.$apply?
另外一个解决方案,以prevent进展中已经消化的错误好像是用$超时:
Another "solution" to prevent "digest already in progress" error seems to be using $timeout:
$timeout(function() {
//...
});
是要走的路?是否安全?因此,这里是真正的问题:我怎样才能的完全消除已经消化进步错误的可能性。
Is that the way to go? Is it safer? So here is the real question: How I can entirely eliminate the possibility of a "digest already in progress" error?
PS:我只使用$范围,非angularjs回调是不同步的$适用。 (据我所知,这些都是,你必须使用$范围的情况下,如果要应用更改$应用)
PS: I am only using $scope.$apply in non-angularjs callbacks that are not synchronous. (as far as I know those are situations where you must use $scope.$apply if you want your changes to be applied)
推荐答案
在一些挖,我是能够解决的问题是否总是安全使用 $范围。$适用
。简短的回答是肯定的。
After some more digging i was able to solve the question whether it's always safe to use $scope.$apply
. The short answer is yes.
龙答:
由于如何浏览器执行JavaScript,因此不可能有两个消化通话碰撞的偶然
Due to how your browser executes Javascript, it is not possible that two digest calls collide by chance.
JavaScript的code我们写的确实一气呵成不是所有的跑,而是轮流执行。每个转弯的运行不间断的从开始到结束,而转弯运行时,没有什么事情发生在我们的浏览器。 (从<一个href=\"http://jimhoskins.com/2012/12/17/angularjs-and-apply.html\">http://jimhoskins.com/2012/12/17/angularjs-and-apply.html)
The JavaScript code we write doesn’t all run in one go, instead it executes in turns. Each of these turns runs uninterupted from start to finish, and when a turn is running, nothing else happens in our browser. (from http://jimhoskins.com/2012/12/17/angularjs-and-apply.html)
因此,错误消化已在进行中只能发生在一种情况:当$敷在内部发出另一个$适用的,例如:
Hence the error "digest already in progress" can only occur in one situation: When an $apply is issued inside another $apply, e.g.:
$scope.apply(function() {
// some code...
$scope.apply(function() { ... });
});
这种情况可以的不可以出现如果我们使用$ scope.apply在纯非angularjs回调,例如像回调的setTimeout
。所以下面code是100%,防弹和有否需要做如果(!$范围。$$阶段)$范围。$适用()
This situation can not arise if we use $scope.apply in a pure non-angularjs callback, like for example the callback of setTimeout
. So the following code is 100% bulletproof and there is no need to do a if (!$scope.$$phase) $scope.$apply()
setTimeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
连这个人是安全的:
even this one is safe:
$scope.$apply(function () {
setTimeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
});
什么是不会安全(因为$超时 - 像所有angularjs助手 - 已调用 $范围$适用
为您服务。):
What is NOT safe (because $timeout - like all angularjs helpers - already calls $scope.$apply
for you):
$timeout(function () {
$scope.$apply(function () {
$scope.message = "Timeout called!";
});
}, 2000);
这也解释了为什么的使用,如果(!$范围。$$阶段)$范围。$适用()
是一个反模式。您只需如果您使用 $范围不需要它适用于$
以正确的方式:在纯JS回调像的setTimeout
例如
This also explains why the usage of if (!$scope.$$phase) $scope.$apply()
is an anti-pattern. You simply don't need it if you use $scope.$apply
in the correct way: In a pure js callback like setTimeout
for example.
读<一个href=\"http://jimhoskins.com/2012/12/17/angularjs-and-apply.html\">http://jimhoskins.com/2012/12/17/angularjs-and-apply.html对于更详细的解释。
这篇关于为什么使用if(!$范围。$$阶段)$范围。$适用()的反模式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!