AngularJS中的$$阶段是什么?

Amo*_*kar 41 angularjs

我发现这段代码片段是某人为bootstrap模态编写的角度指令的一部分.

//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();                                                                                                                                                                                                                                         
                });  
Run Code Online (Sandbox Code Playgroud)

我明白这部分是针对双向绑定的后半部分,我们绑定到hide.bs.modal事件并在UI更改时更新模态.

我只是想知道为什么这个人在调用apply之前检查范围和rootScope的$$阶段?

我们不能直接打电话申请吗?

什么是$$阶段?

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

编辑:

我找到了我看到的例子: Bootstrap Modal的简单角度指令

Dav*_*yon 46

$$phase是一个标志设置,而角度是一个$digest循环.

有时(在极少数情况下),您需要$$phase在执行之前检查范围$apply.如果您尝试在以下$apply期间发生错误$digest:

错误:$申请已在进行中

  • 虽然你的回答在技术上是正确的,但我不同意:恕我直言,你不想经常*检查`$$ phase`*.如果你这样做,它证明缺乏理解如何正确编写AngularJS应用程序.很抱歉这样说,但如果你以正确的方式进行AngularJS,很少需要依赖这个内部(!)变量. (12认同)
  • @GoloRoden是的,完全.谢谢,我已经更新了. (4认同)
  • 只有一个案例,我可以想到你想看看`$$ phase`,那就是当你实现一个"安全应用"时,如果`$ apply`已在进行中,它将直接调用该函数.你唯一一次使用"安全应用"就是当你有一个从角度内和外角有角度调用的函数时......通常可以通过在`$ apply`中包含一个调用并从外部调用它来避免这种情况,但是从里面避开它.我只看到过一种"安全应用"似乎是最佳方法的情况. (3认同)

bet*_*ust 35

达文是完全正确的,它是在消化周期中角度设定的旗帜.

但是不要在你的代码中使用它.

我最近有机会向Misko(有角度的作者)询问关于$$阶段,他说永远不会使用它; 它是摘要周期的内部实现,并不是未来的安全.

为了确保您的代码在将来继续有效,他建议在$ timeout内包装您想要"安全应用"的内容

$timeout(function() {
  // anything you want can go here and will safely be run on the next digest.
})
Run Code Online (Sandbox Code Playgroud)

当你有回调或在摘要周期中可能解决的其他事情时,这会出现很多(但并不总是)

这是我处理谷歌图书馆时的一个示例片段:(其余的服务来自于此.)

window.gapi.client.load('oauth2', 'v2', function() {
    var request = window.gapi.client.oauth2.userinfo.get();
    request.execute(function(response) {
        // This happens outside of angular land, so wrap it in a timeout 
        // with an implied apply and blammo, we're in action.
        $timeout(function() {
            if(typeof(response['error']) !== 'undefined'){
                // If the google api sent us an error, reject the promise.
                deferred.reject(response);
            }else{
                // Resolve the promise with the whole response if ok.
                deferred.resolve(response);
            }
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

请注意,$ timeout的delay参数是可选的,如果未设置则默认为0($ timeout调用$ browser.defer,如果未设置延迟,则默认为0)

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


Bri*_*sio 6

在该示例中,元素绑定将从非角度事件执行.在大多数情况下,只需在$apply()不检查阶段的情况下进行呼叫即可.

但是,如果查看其余代码,则会$scope调用一个函数showModal().此函数调用非角度代码,这可能导致"hide.bs.modal"事件触发.如果事件通过此路由触发,则调用堆栈位于a $digest.

因此,这个事件确实属于一个罕见的函数,它将从角度管理代码和非角度代码中调用.$$phase在这种情况下检查是必要的,因为您不知道事件是如何产生的.如果$$phase设置为某个值,那么摘要循环将完成并且$apply()不需要被调用.

这种模式通常被称为"安全应用".