Getting AngularJS Error: "[$rootScope:inprog] $digest already in progress" without a manual $apply
Asked Answered
L

4

14

Other posts on this error always include someone trying to $apply without using a safe apply, but that's not the case in my example. My function IS successfully returning the data I requested from the API, but I can't clean this bug and it's driving me nuts. Every time before the .success is called in my $http function I get "Error: [$rootScope:inprog] $digest already in progress" in the console. Below are my controller and service. Thanks!

Here's my service including a function to post an $http call with a payload:

Services.service( 'CoolService', ['$q', '$rootScope', '$http', 'Auth', function($q, $rootScope, $http, Auth){
var service = {
    create: function(payload){
        var deferred = $q.defer();
        $http({
            'url': '/api/endpoint/',
            'dataType':'json',
            'method': 'POST',
            data: payload
        }).success(function(data,status, headers, config){
            deferred.resolve(data);

        })
        .error(function(data, status, headers, config){
            deferred.reject("Error in request.");
        });
        return deferred.promise;
        }
    }
    return service;
}]);

And here's my controller which calls the service:

controllers.controller('CoolCtrl',['$scope', '$modal', '$log','CoolService', function($scope, $modal, $log, CoolService){
    getCoolData = function (input_data) {
        CoolService.create(input_data).then(function(results){
            new_cool = results.results;
        }, function(error){
        console.log("there was an error getting new cool data");
        });
    };
    var payload = {
        user_id: data1,
        cool_id: data2,
    }
    var new_cool_data = getCoolData(payload);
    console.log(new_cool_data);
}]);

The log below var new_cool_data gets called before the async operation, but new_cool does get assigned inside the .then statement within getCoolData. Any help getting rid of this bug or making it not crappy in general would be greatly appreciated!

Here's the whole error: https://gist.github.com/thedore17/bcac9aec781ef9ba535b

Lupelupee answered 18/2, 2014 at 15:55 Comment(8)
Do you have any more of the stack trace before the error?Carrizales
This is the whole thing: gist.github.com/thedore17/bcac9aec781ef9ba535bLupelupee
Your error is happening in ui-bootstrap, not your service: (anonymous function) ui-bootstrap-tpls-0.10.0.js:1539Carrizales
That explains a lot, thanks. Anything I can do about it? Technically everything is working, but I feel like it can't be good that I get that error.Lupelupee
Well, it's open source so you could always dig into the ui-bootstrap library. :) Or open an issue on their site.Carrizales
wont new_cool_data be always undefined ? Whats the use of printing it . And yes the error is in ui-bootstrap . We can debug it if you can reproduce it in a plunkrDrastic
Might be a bug in ui-bootstrap: github.com/angular-ui/bootstrap/issues/1798 Could you try 0.11.x ui-bootstrap?Sherrylsherurd
Just to chime in: I had a similar error indicating that bootstrap ui was to blame but it ended up being another directive that was aggressively watching a html container width and needlessly calling scope.$apply(). Are you using any other directives/modules?Decay
T
9

Add this little method and call it inplace of apply()

function CheckScopeBeforeApply() {
    if(!$scope.$$phase) {
         $scope.$apply();
    }
};
Tarazi answered 19/5, 2014 at 15:17 Comment(2)
Yes, this is anti-pattern. See my answer below for an alternative.Mufinella
I am getting the OP error too, however my trace just reports the error is coming from ionic.bundle.js Line 30758, char 9 in a function beginPhase(phase) {if ($rootScope.$$phase) { throw $rootScopeMinErr('inprog', '{0} already in progress', $rootScope.$$phase) ; } $rootScope.$$phase = phase ; }. But its not telling me what triggered it. Through probably 20+ versions of my app over the last two years I have NEVER seen this error before, and its popped up twice when I submitted a new version of the app last night and it looks like either google or apples auto-review of my app triggered it.Herder
M
1

There's an easier solution:

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

Or simply:

$scope.$evalAsync();

This avoids the problems caused by $scope.$apply(), though it should be noted that it won't run immediately (that's part of the reason you won't get the inprog error). I use this instead of $scope.$apply() and it has saved me from so much trouble.

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

Mufinella answered 23/5, 2017 at 23:19 Comment(0)
Y
0

This solve the issue for me. Just add it one time, it you don't need to change you code any more:

https://github.com/angular/angular.js/issues/10083#issuecomment-145967719

.config(function($provide) {
  // Workaround for https://github.com/angular/angular.js/issues/10083
  $provide.decorator('$rootScope', ['$delegate', '$exceptionHandler',
    function($delegate, $exceptionHandler) {
      var proto = Object.getPrototypeOf($delegate);
      var originalDigest = proto.$digest, originalApply = proto.$apply;
      proto.$digest = function() {
        if ($delegate.$$phase === '$digest' || $delegate.$$phase === '$apply') return;
        originalDigest.call(this);
      };
      proto.$apply = function(fn) {
        if ($delegate.$$phase === '$digest' || $delegate.$$phase === '$apply') {
          try {
            this.$eval(fn);
          } catch(e) {
            $exceptionHandler(e);
          }
        } else {
          originalApply.call(this, fn);
        }
      };
      return $delegate;
    }
  ]);
})
Yardman answered 18/11, 2015 at 15:55 Comment(0)
C
0

I used alternate solution by putting $scope.$apply() in timeout like this and it worked...

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

I think it is just because, angular's apply lifecycle was already running and my manual $apply has interrupted it.

Churrigueresque answered 12/2, 2016 at 7:15 Comment(1)
You can use the same for $digest() also.Churrigueresque

© 2022 - 2024 — McMap. All rights reserved.