Error: $digest already in progress

70,887

Solution 1

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

That error you are getting means Angular's dirty checking is already in progress.

Most recent best practices say that we should use $timeout if we want to execute any code in the next digest iteration:

$timeout(function() {
  // the code you want to run in the next digest
});

Previous response: (don't use this approach)

Use a safe apply, like this:

$rootScope.$$phase || $rootScope.$apply();

Why don't you invert the condition?

$scope.$on('$locationChangeStart', function (event, next, current) {                
    if (confirm("Are you sure you want to leave this page?")) {
        event.preventDefault();
    }
});

Solution 2

For others looking to troubleshoot this error, it's worth noting that the docs seem to suggest using the $timeout service to ensure the code will be called in a single $apply block.

$timeout(function() {
  $scope.someData = someData;
});

Also discussed in this question if you look past the accepted answer.

Solution 3

josliber's answer solved a similar $digest problem that I was having. I just used

$scope.$evalAsync(function(){ 
   // code here
});

Good article here https://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm

Solution 4

Use

$scope.evalAsync(function(){ 
});

instead of

$scope.$apply(function(){
});
Share:
70,887
iJade
Author by

iJade

JavaScript enthusiast

Updated on November 19, 2020

Comments

  • iJade
    iJade over 3 years

    I'm getting this error while trying to call

            function MyCtrl1($scope, $location, $rootScope) {
          $scope.$on('$locationChangeStart', function (event, next, current) {
            event.preventDefault();
            var answer = confirm("Are you sure you want to leave this page?");
            if (answer) {
              $location.url($location.url(next).hash());
              $rootScope.$apply();
            }
          });
        }
    
    MyCtrl1.$inject = ['$scope', '$location', '$rootScope'];
    

    Error is

    Error: $digest already in progress
    
  • iJade
    iJade over 11 years
    updated my whole code...its not showing the error now but its not serving the purpose, to go to next view
  • bmleite
    bmleite over 11 years
    Does it pass the if (answer) { condition? What's the content from next?
  • bmleite
    bmleite over 11 years
    Do you get any error on the console? Is there any HTTP request going out?
  • TestyTest
    TestyTest almost 11 years
    To prevent JS lint errors, use this: if (!$scope.$$phase) { $scope.$apply(); }
  • betaorbust
    betaorbust over 10 years
    According to the project, you shouldn't use $$phase becaus it's going away in the future and will break your code. github.com/angular/angular.js/wiki/Anti-Patterns Instead, just wrap anything you think needs a safe apply inside a $timeout. It will safely apply after the current digest cycle.
  • Benxamin
    Benxamin over 9 years
    Use $timeout(). It has an implied $apply that executes on the next digest cycle.
  • Ravi Mane
    Ravi Mane over 8 years
    try with if(!$scope.$$phase) {}
  • Learning-Overthinker-Confused
    Learning-Overthinker-Confused over 8 years
    i was getting same error but using just this code solved this.can you please tell me how does this worked?
  • usersam
    usersam over 6 years
    It worked , but i had to use $scope.$evalAsync(function(){ });