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


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

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

10 121

10 ответов:

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

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

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

https://coderwall.com/p/ngisma

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

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

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

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

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

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

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

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

В моем случае я использую $apply с угловым календарем 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 для планирования изменений области в будущем стеке вызовов. Путем обеспечивать период времени ожидания 0мс, это произойдет как можно скорее, и $timeout гарантирует, что код будет вызван в одном блоке $apply.

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

Подробнее: https://docs.angularjs.org/error/метрики/инпрог?Р0=$применить

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

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

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

Я называю $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();