2017-09-07 14 views
2

저는 아약스를 사용하여 콘텐츠를로드해야하는 컨트롤러가 있습니다. 로딩 중에 중간에 스피너가 나타나기를 바랍니다.

<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 

것은 내가 코드를 단계별로 시도했지만에 관한 짧은 와서 무슨 일이 일어나고 있는지 한 - 와 나는 각 사이클은 그것의 재생 이벤트 루프에서 일어나는 일련의 사건을 오해하고 확신 이 모든 역할.

회 전자가 내가 설정 한 장소가 아닌 약속의 방법으로 표시되도록 설정된 이유에 대해 설명 할 수 있습니까? 실제로 설정되는 것이 아니라 이벤트 루프의 메시지 큐에서 queue'd를 가져 오는 것입니까?

은 ------------ 편집 ------------

나는 무슨 일이 일어나고 있는지에 관한 설명을 가로 질러왔다 생각합니다. @jcford와 @istrupin에게 감사드립니다.

원본 게시물에 누락 된 약간의 재미있는 알림, 약속 통화를 실행하는 이벤트 및 회 전자 업데이트는 사실 현재 $scope.$on("some-name", function(){...}) 이벤트를 기반으로합니다. 즉, 현재 컨트롤러 범위 외부에서 트리거되는 클릭 이벤트입니다. 나는 이것이 이벤트 발생이 해고 된 곳 때문에 $ digest cycle이 일반적으로하는 것처럼 작동하지 않는다고 믿는다. 따라서 $on 함수의 모든 업데이트는 정상적으로하는 것처럼 $ apply/$ digest를 호출하지 않습니다. 즉, $ digest 호출을 특별히 만들어야합니다.

이상하게도, $q.all()에서 $apply을 호출해야하므로 디버깅 할 때 예상 한 DOM 변경 사항을 확인했습니다. Fwiw.

tl; dr - $digest으로 전화하십시오.

+0

제공하시기 바랍니다 [mcve] –

+0

번 대신 NG 쇼의 NG-경우 사용해 볼 수 있습니다. – Ved

+0

약속이 어떻게 작성되었는지 보여줄 수 있습니까? –

답변

1

$scope.isLoadingContent = true을 할당 한 후 $scope.$apply()을 추가 한 후 다이제스트를 강제 실행하십시오. 코드 나머지 부분에 즉시 적용되지 않도록 할 수있는 무언가가있을 수 있습니다.

많은 의견에서 지적했듯이, 이것은 절대적으로 해킹이며 문제를 해결하는 가장 좋은 방법은 아닙니다. 즉 이것이 작동하면 적어도 바인딩이 올바르게 설정되었는지 알 수 있으므로 디버깅을 더 많이 할 수 있습니다. 사용자가 언급 했으므로 다음 단계는 정상적인 다이제스트주기가 엉망이되는지 확인하는 것입니다 (예 : 사용자 JC Ford가 제안한 각도 이외의 트리거링).

+1

$ digest cycle을 강제로 강제 실행하는 이유는 무엇입니까? 모든 각도로. – Ved

+0

'throw $ scope. $ apply()'는 분명히 도움이되지 않습니다.) –

+0

고마워! 그게 효과가 있었어. – mche

-1

일반적으로 isContentLoaded (isLoading에 대한 oposite)를 사용합니다. 처음에는 정의되지 않은 상태로 남겨 두어 ng-show="!isContentLoaded"이 첫 번째 템플릿 반복에서 나타납니다.

모두로드되면 isContentLoaded를 true로 설정합니다.

는 템플릿을 디버깅하려면 먼저 모든 $ 범위 변수 값으로 사이클을 소화 한 직후 코드의 실행을 중지합니다 $timeout(function() { debugger; }) 가 DOM에 반영 $ 제한 시간을 사용해야합니다.

3

두 답변의 조합이 여기에서 트릭을 수행합니다. 사용

$scope.$evalAsync() 

이렇게하면 범위 적용을 좋은 방법으로 결합하게됩니다. $ evalAsync 내의 코드는 현재 다이제스트에 포함되거나 현재 다이제스트가 끝날 때까지 대기 한 다음 변경 사항이있는 새 다이제스트를 시작합니다.

$q.all(promises).then(function (values) { 
    $scope.$evalAsync($scope.isLoadingContent = false); 
}); 
+1

'$ q.then' 안에'$ evalAsync'를 할 필요가 없습니다. $ timeout에 대해 이야기 할 때 디버깅 목적으로 만 언급합니다. –

+0

물론, 'then'함수 내에서 뷰를 즉시 업데이트해야하는 경우가 있습니다. – Mattkwish

+0

$ evalAsync가 없으면 콜백을 실행 한 후에 다이제스트 사이클이 발생하지 않는다고 말하는 것입니까? –