$ 적용 진행 중 오류


133

스택 추적 :

Error: $apply already in progress
at Error (<anonymous>)
at beginPhase (file:///android_asset/www/built.min.js:7:22740)
at Object.Scope.$apply (file:///android_asset/www/built.min.js:7:25967)
at navigator.geolocation.getCurrentPosition.that (file:///android_asset/www/built.min.js:13:8670)
at Object.geolocation.getCurrentPosition (file:///android_asset/www/plugins/org.apache.cordova.core.geolocation/www/geolocation.js:122:13)
at Object.getCurrentPosition (file:///android_asset/www/built.min.js:13:8589)
at Object.getCurrentPosition (file:///android_asset/www/built.min.js:13:8277)
at Object.getCurrentCity (file:///android_asset/www/built.min.js:13:8941)
at Object.$scope.locateDevice (file:///android_asset/www/built.min.js:13:10480)
at file:///android_asset/www/built.min.js:7:12292:7

이 코드를 참조 http://pastebin.com/B9V6yvFu

    getCurrentPosition: cordovaReady(function (onSuccess, onError, options) {

        navigator.geolocation.getCurrentPosition(function () {
            var that = this,
                args = arguments;

            if (onSuccess) {
                $rootScope.$apply(function () {
                    onSuccess.apply(that, args);
                });
            }
        }, function () {
            var that = this,
                args = arguments;
            if (onError) {
                $rootScope.$apply(function () {
                    onError.apply(that, args);
                });
            }
        }, {
            enableHighAccuracy: true,
            timeout: 20000,
            maximumAge: 18000000
        });
    })

이상한 것은 내 LG4X에서는 잘 작동하지만 삼성 s2에서는 위의 오류가 발생합니다. 어떤 아이디어가 잘못 되었습니까?


1
stackoverflow.com/a/12859093/1266600 을 사용해 보셨습니까 ? 다른 장치-> 다른 처리 속도-> 다른 타이밍 때문에 다른 곳에서는 충돌하지 않을 수 있습니다.
sushain97

20
사용$timeout()
Onur Yıldırım

7
$ timeout () 주석에 +1 참조 : stackoverflow.com/questions/12729122/...
트레버

답변:


106

$apply기존 소화주기 내에서 호출하기 때문에이 오류가 발생 합니다.

가장 큰 질문은 : 왜 전화하는 $apply거야? $apply비 앵글 이벤트와 인터페이스하지 않는 한 전화를 걸 필요가 없습니다 . $apply일반적으로 존재한다는 것은 내가 잘못한 것을 의미합니다 (다시 말하지만 $ 적용이 비 Angular 이벤트에서 발생하지 않는 한).

$apply여기에 실제로 적절한 경우 "안전한 적용"접근 방식을 사용해보십시오.

https://coderwall.com/p/ngisma


41
연결된 안전 적용의 핵심은 안티 패턴 (문서에 따라) github.com/angular/angular.js/wiki/Anti-Patterns 입니다. 미래에 지원되는 ($$ phase is away!) 방법을 원한다면 시간을 설정하지 않고 $ timeout ()으로 코드를 감싸십시오. 현재 다이제스트주기가 완료된 후에 안전하게 적용됩니다.
betaorbust

@betaorbust 동의합니다. 안전한 적용이 잘못되었습니다. 또한 적용을 너무 많이 호출하면 성능 문제가 발생할 수 있습니다. 문제를 함께 피하기 위해 코드를 구성하는 것이 가장 좋습니다.
Brian Genisio

im 전화하지 않음
회로


41

이 문장을 사용할 수 있습니다 :

if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') {
    $scope.$apply();
}

1
$$로 시작하는 변수는 개인용 변수이므로 사용하지 않는 것이 좋습니다. 이 경우 $$ phase
Ara Yeressian

9
이 답변은 위의 답변보다 훨씬 유용합니다. 내가 통제 할 수없는 것에 대해 훈계하지 않는 해결책이 필요합니다. 우리는 각도와 레거시 코드가 혼합되어 있으며 어떻게 든 상호 작용해야합니다. 모든 레거시 코드를 다시 작성하기에는 너무 비쌉니다.
Jordan Lapp

24

경우에 따라 범위를 적용해야하는 경우 다음 적용 시간까지 $ apply가 지연되도록 시간 초과를 설정할 수 있습니다.

setTimeout(function(){ scope.$apply(); });

또는 코드를 $ timeout (function () {..}); 실행이 끝날 때 자동으로 범위를 적용합니다. 함수가 동기식으로 작동 해야하는 경우 먼저 할 것입니다.


setTimeout(function() { $apply(function() {... do stuff ...} ) })아래 @Tamil Vendhan에 해당 조치를 포함시켜야 한다는 것을 알았습니다.
프로토 타입

6
setTimeout을 사용하지 마십시오. 다른 $ apply가 필요합니다. 이 프레임 워크를 사용하면 $ timeout 서비스를 통해 모든 것을 수행 할 수 있습니다.
스펜서

10

제 경우 $apply에는 각 캘린더 UI와 함께 사용 하여 일부 이벤트를 연결합니다.

$scope.eventClick = function(event){           
    $scope.$apply( function() {
        $location.path('/event/' + event.id);
    });
};

문제의 문서를 읽은 후 : https://docs.angularjs.org/error/ $ rootScope / inprog

불일치 API (동기화 / 비 동기화) 부분 은 매우 흥미 롭습니다.

예를 들어, 우리를 위해 데이터를 검색하는 방법이있는 타사 라이브러리를 상상해보십시오. 서버에 대한 비동기 호출을 수행 할 수 있기 때문에 데이터가 도착하면 호출되는 콜백 함수를 승인합니다.

MyController 생성자는 항상 $ apply 호출 내에서 인스턴스화되기 때문에 핸들러는 하나에서 $ apply 블록을 새로 입력하려고합니다.

코드를 다음과 같이 변경합니다.

$scope.eventClick = function(event){           
    $timeout(function() {
        $location.path('/event/' + event.id);
    }, 0);
};

매력처럼 작동합니다!

여기서는 $ timeout을 사용하여 향후 호출 스택에서 범위 변경을 예약했습니다. 0ms의 시간 초과 기간을 제공하면 가능한 빨리 발생하며 $ timeout은 단일 $ apply 블록에서 코드가 호출되도록합니다.


1
귀하의 $ timeout delay 0 솔루션은 굉장합니다.
Ahsan

9

각도 1.3에서는 새로운 기능-을 추가했다고 생각 $scope.$applyAsync()합니다. 이 함수 호출은 나중에 적용됩니다-그들은 적어도 약 10ms 후에 말합니다. 완벽하지는 않지만 적어도 성가신 오류를 제거합니다.

https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope # $ applyAsync


3

어느 시점에서나 하나의 작업 $digest또는 $apply진행중인 작업 만있을 수 있습니다 . 이것은 응용 프로그램에 버그가 감지되는 것을 매우 어렵게 방지하기위한 것입니다. 이 오류의 스택 추적을 통해 현재 실행 $apply또는 $digest호출 의 출처를 추적 할 수 있으며 이로 인해 오류가 발생했습니다.

자세한 정보 : https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply


2

이 문제를 방금 해결했습니다. 여기에 문서화되어 있습니다 .

$rootScope.$apply같은 흐름으로 두 번 전화 했습니다. 내가 한 것은 서비스 함수의 내용을로 감싸는 것 setTimeout(func, 1)입니다.


1

나는 그것이 오래된 질문이라는 것을 알고 있지만 정말로 필요한 경우 $ scope. $ applyAsync ();


0

한 번에 여러 번 호출을 무시하려면 $ scope. $ apply를 호출하십시오.

      var callApplyTimeout = null;
      function callApply(callback) {
          if (!callback) callback = function () { };
          if (callApplyTimeout) $timeout.cancel(callApplyTimeout);

          callApplyTimeout = $timeout(function () {
              callback();
              $scope.$apply();
              var d = new Date();
              var m = d.getMilliseconds();
              console.log('$scope.$apply(); call ' + d.toString() + ' ' + m);
          }, 300);
      }

단순히 전화

callApply();
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.