Dominik Goltermann
Dominik Goltermann

Reputation: 4306

Is it always save to use $scope.$apply?

Sometimes i need to use $scope.$apply, for example when i use jQuery ajax or some non-angular-js eventlisteners. In those cases i have an asynchronous callback and there i use $scope.$apply so that changes to the scope are picked up by angular and watches are triggered. Please correct me if that is the wrong use of $scope.$apply.

This seems to work and the view is updated. However in some rather rare cases I get a "digest already in progress" error. I don't see how this can be possible, since the callback is not synchronous. So I wonder if it is possible that my asynchronous callback with the $scope.$apply in it can by chance collide with an ongoing digest? If so, how can I prevent this from happening?

edit:

One possibility to check for a digest is checking $$phase: if (!$scope.$$phase) $scope.$apply() but this is an anti-pattern as the angularjs wiki says: https://github.com/angular/angular.js/wiki/Anti-Patterns

I want to fully understand why it is possible that I encounter a digest in an asynchronous callback. And why this is an antipattern.

Upvotes: 4

Views: 601

Answers (4)

Matt Pileggi
Matt Pileggi

Reputation: 7196

You are calling $apply on an existing scope, so it's definitely possible that you are calling apply while it is currently digesting. Some people might suggest checking $$phase but that has been discouraged as an anti-pattern

You have two options if you are running into this problem, even occasionally. One is to do as the anti-pattern implies and make sure your $scope.$apply is as high as possible up the chain.

However, this won't help if you are asynchronously calling $apply on the same $scope in rapid succession. The answer then is often to throttle the $apply so that it only happens every few hundred milliseconds. This is a common practice when using something like socket.io that can fire events which could cause you to re-apply many times.

Upvotes: 1

Dominik Goltermann
Dominik Goltermann

Reputation: 4306

I recently asked a similiar question on why if (!$scope.$$phase) $scope.$apply() is an anti-pattern here: Why is using if(!$scope.$$phase) $scope.$apply() an anti-pattern?

The answer there also contains the answer to this question.

Upvotes: 1

Gent
Gent

Reputation: 2685

Async Callbacks are an appropriate time to use the $apply, there are edgecases I have run into as well where i get that error. They are usually because I am doing something wonky, I have found that a "Conditional Apply" works well for these.

if(!$scope.$$phase) {
  //$digest or $apply
}

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

Upvotes: 0

Vasiliy vvscode Vanchuk
Vasiliy vvscode Vanchuk

Reputation: 7159

I think, that its normal, but it will be better to move code to services and resources with angular style. To prevent error you can check current state

scope.$$phase

To prevent calling $apply

Upvotes: 0

Related Questions