[angularjs] $apply already in progress error

Stack trace:

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

refers to this code 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
        });
    })

Strange thing, on my LG4X it works fine, however on my samsung s2 it throws the above error. Any ideas whats wrong?

This question is related to angularjs cordova angularjs-digest

The answer is


We can use setTimeout function in such cases.

console.log('primary task');

setTimeout(function() {
  
  console.log('secondary task');

}, 0);

This will make sure that secondary task will be executed when execution of primary task is finished.


In my case i use $apply with angular calendar UI to link some event:

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

After reading the doc of the problem: https://docs.angularjs.org/error/$rootScope/inprog

The part Inconsistent API (Sync/Async) is very interesting:

For example, imagine a 3rd party library that has a method which will retrieve data for us. Since it may be making an asynchronous call to a server, it accepts a callback function, which will be called when the data arrives.

Since, the MyController constructor is always instantiated from within an $apply call, our handler is trying to enter a new $apply block from within one.

I change the code to :

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

Works like a charm !

Here we have used $timeout to schedule the changes to the scope in a future call stack. By providing a timeout period of 0ms, this will occur as soon as possible and $timeout will ensure that the code will be called in a single $apply block.


I call $scope.$apply like this to ignored call multiple in one times.

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

simply call

callApply();

Just use $evalAsync instead of $apply.


At any point in time, there can be only one $digest or $apply operation in progress. This is to prevent very hard to detect bugs from entering your application. The stack trace of this error allows you to trace the origin of the currently executing $apply or $digest call, which caused the error.

More info: https://docs.angularjs.org/error/$rootScope/inprog?p0=$apply


I know it's old question but if you really need use $scope.$applyAsync();


Just resolved this issue. Its documented here.

I was calling $rootScope.$apply twice in the same flow. All I did is wrapped the content of the service function with a setTimeout(func, 1).


You can use this statement:

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

If scope must be applied in some cases, then you can set a timeout so that the $apply is deferred until the next tick

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

or wrap your code in a $timeout(function(){ .. }); because it will automatically $apply the scope at the end of execution. If you need your function to behave synchronously, I'd do the first.


In angular 1.3, I think, they added a new function - $scope.$applyAsync(). This function calls apply later on - they say about 10 ms later at least. It is not perfect, but it does at least eliminate the annoying error.

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


You can $apply your changes only if $apply is not already in progress. You can update your code as

if(!$scope.$$phase) $scope.$apply();

Examples related to angularjs

AngularJs directive not updating another directive's scope ERROR in Cannot find module 'node-sass' CORS: credentials mode is 'include' CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 Print Html template in Angular 2 (ng-print in Angular 2) $http.get(...).success is not a function Angular 1.6.0: "Possibly unhandled rejection" error Find object by its property in array of objects with AngularJS way Error: Cannot invoke an expression whose type lacks a call signature

Examples related to cordova

Why am I seeing net::ERR_CLEARTEXT_NOT_PERMITTED errors after upgrading to Cordova Android 8? Xcode couldn't find any provisioning profiles matching Cordova app not displaying correctly on iPhone X (Simulator) JAVA_HOME is set to an invalid directory: ionic 2 - Error Could not find an installed version of Gradle either in Android Studio cordova Android requirements failed: "Could not find an installed version of Gradle" Error: Could not find gradle wrapper within Android SDK. Might need to update your Android SDK - Android Ionic 2: Cordova is not available. Make sure to include cordova.js or run in a device/simulator (running in emulator) Cordova : Requirements check failed for JDK 1.8 or greater Can't accept license agreement Android SDK Platform 24

Examples related to angularjs-digest

$apply already in progress error AngularJS : Prevent error $digest already in progress when calling $scope.$apply()