Ślad stosu:
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
odnosi się do tego kodu 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
});
})
Dziwne, na moim LG4X działa dobrze, jednak na moim Samsungu s2 wyrzuca powyższy błąd. Jakieś pomysły, co się stało?
angularjs
cordova
angularjs-digest
Głosuj za
źródło
źródło
$timeout()
Odpowiedzi:
Otrzymujesz ten błąd, ponieważ dzwonisz
$apply
w ramach istniejącego cyklu trawienia.Najważniejsze pytanie brzmi: dlaczego dzwonisz
$apply
? Nigdy nie powinieneś dzwonić,$apply
chyba że łączysz się z wydarzeniem innym niż Angular. Istnienie$apply
zwykle oznacza, że robię coś złego (chyba że, ponownie, $ zastosuj dzieje się ze zdarzenia innego niż Angular).Jeśli
$apply
naprawdę jest to właściwe, rozważ zastosowanie podejścia „bezpiecznego stosowania”:https://coderwall.com/p/ngisma
źródło
Po prostu użyj $ evalAsync zamiast
$apply
.źródło
Możesz użyć tego oświadczenia:
if ($scope.$root.$$phase != '$apply' && $scope.$root.$$phase != '$digest') { $scope.$apply(); }
źródło
Jeśli w niektórych przypadkach trzeba zastosować zakres, możesz ustawić limit czasu, aby $ Apply odłożyć do następnego tiku
setTimeout(function(){ scope.$apply(); });
lub zawiń swój kod w $ timeout (function () {..}); ponieważ automatycznie zastosuje zakres po zakończeniu wykonywania. Jeśli chcesz, aby Twoja funkcja zachowywała się synchronicznie, zrobię to w pierwszej kolejności.
źródło
setTimeout(function() { $apply(function() {... do stuff ...} ) })
per @Tamil Vendhan.W moim przypadku używam
$apply
interfejsu kalendarza kątowego do łączenia niektórych wydarzeń:$scope.eventClick = function(event){ $scope.$apply( function() { $location.path('/event/' + event.id); }); };
Po przeczytaniu dokumentacji problemu: https://docs.angularjs.org/error/ $ rootScope / inprog
Część niespójna API (Sync / Async) jest bardzo interesująca:
Zmieniam kod na:
$scope.eventClick = function(event){ $timeout(function() { $location.path('/event/' + event.id); }, 0); };
Działa jak marzenie !
źródło
Myślę, że w kątowej 1.3 dodali nową funkcję -
$scope.$applyAsync()
. Te wywołania funkcji mają zastosowanie później - mówią co najmniej 10 ms później. Nie jest doskonały, ale przynajmniej eliminuje irytujący błąd.https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope # $ applyAsync
źródło
W dowolnym momencie może być tylko jedna operacja
$digest
lub$apply
w toku. Ma to na celu zapobieżenie bardzo trudnym do wykrycia błędom przed wejściem do aplikacji. Śledzenie stosu tego błędu umożliwia śledzenie pochodzenia aktualnie wykonywanego$apply
lub$digest
wywołania, które spowodowało błąd.Więcej informacji: https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply
źródło
Właśnie rozwiązałem ten problem. Jest to udokumentowane tutaj .
Dzwoniłem
$rootScope.$apply
dwa razy w tym samym strumieniu. Wszystko, co zrobiłem, to opakowanie zawartości funkcji usługi rozszerzeniemsetTimeout(func, 1)
.źródło
Wiem, że to stare pytanie, ale jeśli naprawdę potrzebujesz, użyj $ scope. $ ApplyAsync ();
źródło
Wywołuję $ scope. $ Zastosuj w ten sposób, aby zignorować wywołanie wiele razy w jednym czasie.
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); }
po prostu zadzwoń
callApply();
źródło
setTimeout
W takich przypadkach możemy użyć funkcji.console.log('primary task'); setTimeout(function() { console.log('secondary task'); }, 0);
Zapewni to, że zadanie dodatkowe zostanie wykonane po zakończeniu wykonywania zadania podstawowego.
źródło