$ uygulama zaten devam ediyor hatası


133

Yığın izleme:

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

bu kodu ifade eder 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
        });
    })

Garip bir şey, LG4X'imde iyi çalışıyor, ancak samsung s2 cihazımda yukarıdaki hatayı atıyor. Neyin yanlış olduğu hakkında bir fikriniz var mı?


1
Stackoverflow.com/a/12859093/1266600'ü denediniz mi? Bunun nedeni, farklı cihazların -> farklı işlem hızlarının -> farklı zamanlamaların, bazı yerlerde çatışmalara neden olabilirken diğerlerinde neden olamayacağı olabilir.
sushain97

20
kullanım$timeout()
Onur Yıldırım

7
$ Timeout () yorumuna + 1'leyin. Bakınız: stackoverflow.com/questions/12729122/…
Trevor

Yanıtlar:


106

Bu hatayı alıyorsunuz çünkü $applymevcut bir sindirim döngüsünün içinde arıyor olabilirsiniz .

Büyük soru şu: neden $applyarıyorsun? $applyAçısal olmayan bir olaydan arabirim oluşturmadığınız sürece aramanıza asla gerek yoktur . Varlığı $applygenellikle yanlış bir şey yaptığım anlamına gelir (yine, $ apply Angular olmayan bir olaydan meydana gelmedikçe).

Eğer $applygerçekten burada uygun bir yaklaşım "güvenli uygulamak" kullanmayı düşünün:

https://coderwall.com/p/ngisma


41
Bağlantılı güvenli uygulamanın özü bir anti-modeldir (belgelere göre) github.com/angular/angular.js/wiki/Anti-Patterns . Gelecekte desteklenen ($$ aşaması ortadan kalkıyor!) Bir yöntem istiyorsanız, kodunuzu zaman ayarı olmaksızın bir $ zaman aşımına () sarın. Mevcut sindirim döngüsü tamamlandıktan sonra güvenle uygulanacaktır.
betaorbust

@betaorbust Kabul Edildi. Güvenli başvuru kötüdür. Ayrıca, çok fazla kez başvurmak, mükemmel sorunlara neden olabilir. En iyisi, sorunu hep birlikte önlemek için kodu yapılandırmaktır.
Brian Genisio

uygulama çağırmıyorum
devre


41

Bu ifadeyi kullanabilirsiniz:

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

1
$$ ile başlayan değişkenlerin özel olmaları nedeniyle kullanılması önerilmez. Bu durumda $$ aşaması
Ara Yeressian

9
Bu cevap yukarıdakinden çok daha faydalıdır. Kontrolüm dışında olabilecek bir şey için uyarılmak değil, bir çözüme ihtiyacım var. Açısal ve eski kodun bir karışımına sahibiz ve bir şekilde etkileşime girmeleri gerekiyor. Tüm eski kodu yeniden yazmak çok pahalı ...
Jordan Lapp

24

Bazı durumlarda kapsamın uygulanması gerekiyorsa, bir zaman aşımı ayarlayabilirsiniz, böylece $ uygulaması bir sonraki tıklamaya kadar ertelenir.

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

veya kodunuzu bir $ zaman aşımına (function () {..}) sarın; çünkü yürütme sonunda kapsamı otomatik olarak $ uygulayacaktır. İşlevinizin eşzamanlı davranmasına ihtiyacınız varsa, ilkini yapacağım.


Ben içinde harekete dahil etmek gerekli buldum setTimeout(function() { $apply(function() {... do stuff ...} ) })aşağıda @Tamil Vendhan başına.
prototip

6
SetTimeout'u kullanmayın, bu sadece başka bir $ apply gereksinimi yaratır. Çerçeveyi kullanın, sizin için tüm bunları yapan bir $ zaman aşımı hizmetine sahiptir.
Spencer

10

Benim durumumda, $applybazı etkinlikleri birbirine bağlamak için açısal takvim kullanıcı arayüzüyle kullanıyorum :

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

Sorunun belgesini okuduktan sonra: https://docs.angularjs.org/error/ $ rootScope / inprog

Inconsistent API (Sync / Async) bölümü çok ilginç:

Örneğin, bizim için verileri alacak bir yönteme sahip bir 3. taraf kitaplığı hayal edin. Bir sunucuya eşzamansız bir çağrı yapıyor olabileceğinden, veri geldiğinde çağrılacak olan bir geri arama işlevini kabul eder.

MyController kurucusu her zaman bir $ apply çağrısı içinden somutlaştırıldığı için, işleyicimiz bir içinden yeni bir $ apply bloğu girmeye çalışıyor.

Kodu şu şekilde değiştiriyorum:

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

Tıkır tıkır çalışıyor !

Burada, gelecekteki bir çağrı yığınında kapsamdaki değişiklikleri planlamak için $ timeout kullandık. 0ms'lik bir zaman aşımı süresi sağlayarak, bu mümkün olan en kısa sürede gerçekleşir ve $ zaman aşımı, kodun tek bir $ apply bloğunda çağrılmasını sağlar.


1
$ Timeout delay 0 çözümünüz Harika.
Ahsan

9

Açısal 1.3'te, yeni bir işlev eklediklerini düşünüyorum - $scope.$applyAsync(). Bu işlev çağrıları daha sonra geçerli - en az 10 ms sonra diyorlar. Mükemmel değil, ama en azından can sıkıcı hatayı ortadan kaldırıyor.

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


3

Herhangi bir zamanda, devam eden tek bir işlem $digestveya $applyişlem olabilir . Bu, çok zor hataların uygulamanıza girmesini önlemek içindir. Bu hatanın yığın izlemesi, o anda yürütülen $applyveya $digesthataya neden olan çağrının kaynağını izlemenize olanak tanır .

Daha fazla bilgi: https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply


2

Bu sorunu az önce çözdüm. Onun belgelenmiş burada .

$rootScope.$applyAynı akışta iki kez arıyordum . Tek yaptığım, hizmet işlevinin içeriğini bir setTimeout(func, 1).


1

Eski bir soru olduğunu biliyorum ama gerçekten $ kapsam kullanmanız gerekiyorsa $ applyAsync ();


0

Bir seferde çoklu çağrıyı yok saymak için $ kapsam. $ Böyle uygula.

      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);
      }

sadece ara

callApply();
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.