$ применить уже выполненную ошибку

Трассировка стека:

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 она отлично работает, однако на моем samsung s2 она выдает указанную выше ошибку. Какие-нибудь идеи в чем-то не так?

Ответ 1

Вы получаете эту ошибку, потому что вы вызываете $apply внутри существующего цикла пищеварения.

Большой вопрос: зачем вы звоните $apply? Вам не нужно будет звонить $apply, если вы не взаимодействуете с событием не Angular. Существование $apply обычно означает, что я делаю что-то неправильно (если, опять же, $apply не происходит из события Angular).

Если $apply действительно здесь уместно, подумайте об использовании подхода "безопасного применения":

https://coderwall.com/p/ngisma

Ответ 2

Просто используйте $evalAsync вместо $apply.

Ответ 3

Вы можете использовать это утверждение:

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

Ответ 4

Если в некоторых случаях необходимо применить область видимости, тогда вы можете установить тайм-аут так, чтобы $apply откладывался до следующего тика

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

или оберните свой код в $timeout (function() {..}); потому что он автоматически присваивает объем в конце выполнения. Если вам нужно, чтобы ваша функция вела себя синхронно, я бы сделал первый.

Ответ 5

В angular 1.3, я думаю, они добавили новую функцию - $scope.$applyAsync(). Вызов этой функции применяется позже - они говорят, по меньшей мере, через 10 мс позже. Это не идеально, но, по крайней мере, устраняет раздражающую ошибку.

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

Ответ 6

В моем случае я использую $apply с angular Calendar UI, чтобы связать какое-то событие:

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

После прочтения документа проблемы: https://docs.angularjs.org/error/ $rootScope/inprog

Непоследовательная API (Sync/Async) очень интересна:

Например, представьте себе стороннюю библиотеку, которая имеет метод, который будет извлекать данные для нас. Поскольку он может выполнять асинхронный вызов на сервере, он принимает функцию обратного вызова, которая будет вызываться при поступлении данных.

Так как конструктор MyController всегда создается из вызова $apply, наш обработчик пытается ввести новый блок $apply изнутри.

Я меняю код на:

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

Работает как шарм!

Здесь мы использовали $timeout для планирования изменений в области в будущем стеке вызовов. Предоставляя период ожидания 0ms, это произойдет как можно скорее, а $timeout будет гарантировать, что код будет вызываться в одном блоке $apply.

Ответ 7

В любой момент времени может выполняться только одна операция $digest или $apply. Это делается для того, чтобы предотвратить очень сложное обнаружение ошибок при вводе вашего приложения. Трассировка стека этой ошибки позволяет проследить происхождение текущего вызова $apply или $digest, вызвавшего ошибку.

Дополнительная информация: https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply

Ответ 8

Просто разрешил эту проблему. Его документированный здесь.

Я дважды звонил $rootScope.$apply в один поток. Все, что я сделал, завернуло содержимое сервисной функции с помощью setTimeout(func, 1).

Ответ 9

Я вызываю $scope. $применяется так, чтобы игнорировать вызов несколько раз за один раз.

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

Ответ 10

Я знаю старый вопрос, но если вам действительно нужно использовать $scope. $applyAsync();