AngularJS中的$$阶段是什么?

AngularJS中的$$阶段是什么?,angularjs,Angularjs,我发现了这个代码片段,它是有人为引导模式编写的angular指令的一部分 //Update the visible value when the dialog is closed

我发现了这个代码片段,它是有人为引导模式编写的angular指令的一部分

//Update the visible value when the dialog is closed                                                                                                                                                                                                            
                //through UI actions (Ok, cancel, etc.)                                                                                                                                                                                                                         
                element.bind("hide.bs.modal", function () {                                                                                                                                                                                                                     
                    scope.modalVisible = false;                                                                                                                                                                                                                                 
                    if (!scope.$$phase && !scope.$root.$$phase)                                                                                                                                                                                                                 
                        scope.$apply();                                                                                                                                                                                                                                         
                });  
我知道这部分是用于双向绑定的后半部分,我们绑定到hide.bs.modal事件,并在UI更改时更新modal

我只是想知道为什么这个人在调用apply之前要检查$$phase的scope和rootScope

我们不能马上打电话申请吗

这里的$$阶段是什么

我找了很多,找不到任何好的解释

编辑:

我找到了我看到示例的地方:
$$phase
是在角度处于
$digest
周期时设置的标志

有时(在极少数情况下),您希望在执行
$apply
之前检查作用域上的
$$phase
。如果在
$digest
期间尝试
$apply
,则会发生错误:

错误:$apply已在进行中


在该示例中,元素绑定将从非角度事件执行。在大多数情况下,只调用
$apply()
而不检查阶段是安全的

但是,如果您查看代码的其余部分,就会发现有一个名为
showModal()
$scope
函数。此函数调用非角度代码,这可能会引发“hide.bs.modal”事件。如果事件通过此路由触发,则调用堆栈位于
$digest

因此,这个事件确实属于从角度托管代码和非角度代码调用函数的罕见情况。在这种情况下,有必要检查
$$阶段
,因为您不知道事件是如何起源的。如果
$$phase
设置为某个值,则摘要循环将完成,并且不需要调用
$apply()


这种模式通常被称为

Davin完全正确,这是一个在消化周期中角度设置的标志

但不要在代码中使用它。

我最近有机会问Misko(angular author)关于$$phase的事,他说永远不要用它;它是摘要周期的一个内部实现,对未来不安全

为了确保您的代码在将来继续工作,他建议在$timeout内包装您想要“安全应用”的任何内容

$timeout(function() {
  // anything you want can go here and will safely be run on the next digest.
})
当您在摘要周期中遇到回调或其他可能解决的问题时(但并非总是如此),会经常出现这种情况

下面是我在处理谷歌的一个库时的一个示例片段:(该服务的其余部分已被取消)

请注意,$timeout的delay参数是可选的,如果未设置,它将默认为0(调用)


有点不直观,但这是写Angular的人的答案,所以对我来说已经足够好了

我的理解是,在消化或应用范围时使用它是很好的。如果是真的,则表示当前正在进行$digest或$apply阶段。如果遇到相关错误,可以执行$scope。$$phase | |$scope.digest();只有在$scope.$$pahse是错误的情况下,它才会被消化。

您可以使用
$scope.$evalAsync()
方法,而不是使用
$scope.$apply()
外部的
$phase
值检查,正如@betaorbust正确建议的那样:

我最近有机会问Misko(angular author)关于$$phase的事,他说不要使用它这是消化周期的内部实现,对未来不安全

$scope.$evalAsync()
的好处在于,它提供了您真正想要的,在摘要周期中更新新数据,甚至比$timeout还快:

到目前为止,我的延迟-$digest调用方法是用$timeout()服务(在延迟后隐式调用$apply())替换$scope.$apply()调用。但是,昨天,我发现了$scope.$evalAsync()方法。这两种方法都完成了相同的任务——它们将表达式计算推迟到稍后的时间点。但是,$scope.$evalAsync()可能在JavaScript事件循环的同一个周期中执行

用法非常简单:

$scope.$evalAsync(
    function() {
       // Call some method here OR 
       $scope.excutemyMethod(); 

       // assign some value;
       $scope.someVariable = "asd"

    }
);
$evalAsync()
中的方法被添加到异步队列中,这样就可以通过内部触发
$apply
在下面的摘要周期中执行它,这正是我们真正想要的


它还包括
$timeout
调用,用于处理最罕见的场景,观察异步队列长度并等待异步队列中的任务执行,以便尽快将函数放入执行周期。参考,这就解释了这个事实。

虽然你的答案在技术上是正确的,但我不同意:不,你不想经常检查
$$phase
。如果你这样做了,那就证明你不了解如何正确编写AngularJS应用程序。很抱歉这么说,但是如果你用正确的方法做AngularJS,那么很少有需要依赖这个内部(!)变量的情况!这件事:“$digest在调用$scope时已经在进行中。$apply()”@AmoghTalpallikar您的问题不够具体,无法处理您的具体情况。从理论上讲,
$$phase
可以防止此错误。也许你可以提供一个更详细的例子?还是关于细节的另一个问题?:)我能想到的只有一种情况是,您希望在哪里查看
$$phase
,即当您实现“安全应用”时,如果
$apply
已经在进行中,它将直接调用函数。唯一一次你会使用“安全应用”是当你有一个函数,从内部角度和外部角度调用。。。但这通常可以通过在
$apply
中封装一个调用并从外部调用来避免,但要从内部避免调用。我只见过一种情况,“安全应用”看起来是最好的
$scope.$evalAsync(
    function() {
       // Call some method here OR 
       $scope.excutemyMethod(); 

       // assign some value;
       $scope.someVariable = "asd"

    }
);