我有一个控制器,我需要使用AJAX加载内容。在加载时,我希望一个旋转器出现在过渡期。该代码看起来像以下内容:
<i class="fa fa-2x fa-spin fa-spinner" ng-show="isLoadingContent"></i>
和相应的JS:
$scope.isLoadingContent = true;
$q.all(promises).then(function (values) {
$scope.isLoadingContent = false;
// more code - display returned data
但是,UI旋转器不会出现/当我期望逐步浏览代码时出现的位置。
$scope.isLoadingContent = true;
debugger; // the spinner does not appear on the UI
$q.all(promises).then(function (values) {
debugger; // the spinner finally does appear in the UI at this point
$scope.isLoadingContent = false;
// more code - display returned data
我尝试介绍该代码,但在发生了什么事 - 而且我确信我会误解事件循环中发生的事件的顺序以及角循环在所有这些中所扮演的角色。
有人能够提供有关为什么旋转器设置在承诺方法中而不是我设置$scope.isLoadingContent
的位置的解释?它实际上不是设置的,而是在事件环的消息标题中排队吗?
-------------编辑---------------
我相信我遇到了有关发生的事情的解释。在很大程度上要感谢@jcford和@istrupin。
因此,在原始帖子中缺少一些小平台,事件触发呼叫和旋转器更新实际上是基于$scope.$on("some-name", function(){...})
事件的 - 有效地是在我当前控制器范围之外触发的点击事件。我相信这意味着$摘要周期无法正常工作,因为事件形成的位置被解散了。因此,$on
函数中的任何更新都不会像平常一样调用$ apply/$摘要,这意味着我必须专门进行$ impeast调用。
奇怪的是,我现在意识到,在$q.all()
中,它必须调用$apply
,因为在调试时,我看到了我所期望的DOM更改。fwiw。
tl; dr-调用 $digest
。
两个答案的组合将在这里解决问题。使用
$scope.$evalAsync()
这将结合范围申请与超时的良好方式。$ evalasync中的代码要么包含在当前摘要中,要么等到当前摘要结束并随您的更改启动新的摘要。
即。
$q.all(promises).then(function (values) {
$scope.$evalAsync($scope.isLoadingContent = false);
});
分配$scope.isLoadingContent = true
强迫摘要后,尝试添加$scope.$apply()
。在您的其余代码中可能会有某些东西使其无法立即申请。
正如许多评论中指出的那样,这绝对是一个黑客,也不是解决问题的最佳方法。也就是说,如果确实有效,您至少知道自己的绑定设置正确,这将使您可以进一步调试。既然您提到了它,那么下一步将是查看是什么搞砸了正常的摘要周期 - 例如,如用户JC福特所建议的。
我通常使用isContentLoaded(作为oposite ton Isloading)。我首先将其保留不确定,因此ng-show="!isContentLoaded"
可以在第一个模板迭代中显示出来。
全部加载时,我将iScontentloade设置为true。
要调试模板,您需要使用$超时 $timeout(function () { debugger; })
这将在第一次摘要周期后立即停止代码执行,并在DOM中反映的所有$ scope变量值。