dman
dman

Reputation: 11073

Angular.js - Had to use $apply() even though a $digest() was already in progress -why?

In my Angular.js Service, I had to use $rootScope.$apply() so the scope primitive values would update in the view.

  function scopeMutateSuccess(modalInstance, state){
    //always worried about name collisions, so not 
    //useing $ to be safe
    modalEventConfig.statusType = 'success';
    modalEventConfig.nodeStatus = 'Completed Successfully';
    $rootScope.$apply();
    setTimeout(function() {
      return modalInstance.close();
    }, TIME_CLOSE_MODAL);
    state.forceReload();
  }

For learning...I am curious:

1) $digest() is cheaper than $apply() since it is just to local scope...but would this matter on $rootScope since it would transverse down to all child scopes?

2) For experimenting, I tried rootScope.$digest() and I got a error message saying a digest was already in progress. If this is so-

Upvotes: 0

Views: 90

Answers (1)

Maxim Shoustin
Maxim Shoustin

Reputation: 77930

The $digest() is a trigger for watchers only, when $apply - 1st runs logic wrapped by $apply method and only after runs $rootScope.$digest()

why didn't this error occur when $apply() was used since it also calls $digest()

$exceptionHandler doesn't handle $scope.$digest when $scope.$apply does (try/catch)


Tips:

  • Its not good practice to use setTimeout when Angular provides $timeout method.
  • Instead to call $rootScope.$apply();

I would better use block style like:

$rootScope.$apply(function(){                    
 // do your stuff here
});

You always can check if code runs the digest cycle with some method:

isScopeOutCycle: function () {
        return $rootScope.$root.$$phase != '$apply' && $rootScope.$root.$$phase != '$digest';
} 

Upvotes: 1

Related Questions