0

It seems that one can achieve the same result using two different approaches:

doSomething();
$scope.$digest();

or

$scope.$apply(function() {
  doSomething();
});

So what are the differences and what to use when?

Matthias
  • 13,607
  • 9
  • 44
  • 60
Mike
  • 20,010
  • 25
  • 97
  • 140
  • There are a lot of answers for this question already http://stackoverflow.com/questions/35826219/angular-scope-digest-vs-scope-apply or https://www.sitepoint.com/understanding-angulars-apply-digest/ – antonama Dec 27 '16 at 11:53

4 Answers4

2

AngularJS $digest

Processes all of the watchers of the current scope and its children. Because a watcher's listener can change the model, the $digest() keeps calling the watchers until no more listeners are firing. This means that it is possible to get into an infinite loop. This function will throw 'Maximum iteration limit exceeded.' if the number of iterations exceeds 10.

Usually, you don't call $digest() directly in controllers or in directives. Instead, you should call $apply() (typically from within a directive), which will force a $digest().

If you want to be notified whenever $digest() is called, you can register a watchExpression function with $watch() with no listener.

In unit tests, you may need to call $digest() to simulate the scope life cycle.

Community
  • 1
  • 1
NechiK
  • 341
  • 2
  • 11
1

Both will do the same thing. But, using $scope.apply() wrapped as a function is best practice. Why because, when you wrap something in $scope.apply(), you can write catch block for that. So, you can catch any exceptions you may face.

Sai M.
  • 2,548
  • 4
  • 29
  • 46
  • I can write catch block in both cases around `doSomething()`, not? – Mike Dec 27 '16 at 11:55
  • @MykhayloAdamovych, If your code isn’t wrapped in a function passed to $apply, and it throws an error, that error is thrown outside of AngularJS, which means any error handling being used in your application is going to miss it. $apply not only runs your code, but it runs it in a try/catch so your error is always caught, and the $digest call is in a finally clause, meaning it will run regardless of an error being thrown. – Sai M. Dec 27 '16 at 12:10
1

You can check if a $digest is already in progress by checking $scope.$$phase.

if(!$scope.$$phase) {
  //use anyone yours: $digest or $apply
}

scope.$digest() will fire watchers on the current scope, and on all of its children, too. scope.$apply will evaluate passed function and run $rootScope.$digest().

See this: $apply vs $digest in directive testing

Community
  • 1
  • 1
Avnesh Shakya
  • 3,828
  • 2
  • 23
  • 31
  • There is no use to do that as you may mark scope dirty many times but digest cycle will be started once and clear the flag. – Mike Dec 27 '16 at 12:33
1

$scope.$digest() : This is cycle process. So when we call $scope.$digest() it will start a digest cycle and check all the watchers of the scope whatever should changed will be changed, and after that a dirty check will be processed , which will check while the digest cycle was is progress is anything changed , if changed then again the digest cycle will start working.One Should not call $scope.$digest() manually because whenever anything change in the scope it will be called . More details here $digest

$scope.$apply: In $scope.$apply you implicitly tell that only watchers affected by the function will be update or only specific watchers will be checked for the update,it handles exception internally , no manual handling needed . More details $apply

Viplock
  • 3,259
  • 1
  • 23
  • 32