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

TedCap
  • 185
  • 1
  • 1
  • 9
  • Do you have any more of the stack trace before the error? – Geoff Genz Feb 18 '14 at 16:01
  • This is the whole thing: https://gist.github.com/thedore17/bcac9aec781ef9ba535b – TedCap Feb 18 '14 at 16:58
  • 1
    Your error is happening in ui-bootstrap, not your service: (anonymous function) ui-bootstrap-tpls-0.10.0.js:1539 – Geoff Genz Feb 18 '14 at 17:39
  • 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. – TedCap Feb 18 '14 at 20:41
  • Well, it's open source so you could always dig into the ui-bootstrap library. :) Or open an issue on their site. – Geoff Genz Feb 18 '14 at 20:47
  • 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 plunkr – Abhik Apr 06 '14 at 11:57
  • Might be a bug in ui-bootstrap: https://github.com/angular-ui/bootstrap/issues/1798 Could you try 0.11.x ui-bootstrap? – aet May 06 '14 at 02:07
  • 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? – Cory Silva May 16 '14 at 01:23

4 Answers4

9

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

function CheckScopeBeforeApply() {
    if(!$scope.$$phase) {
         $scope.$apply();
    }
};
HandyManDan
  • 148
  • 1
  • 6
  • Yes, this is anti-pattern. See my answer below for an alternative. – Sam May 23 '17 at 23:21
  • 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. – rolinger May 25 '22 at 12:36
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

Sam
  • 845
  • 7
  • 20
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;
    }
  ]);
})
Aminadav Glickshtein
  • 23,232
  • 12
  • 77
  • 117
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.