Mystery between $scope.apply(); and $scope.apply(function(){})

When you make a change outside of a non-Angular method, so a native DOM event or method in a third party library like jQuery, Angular does not know anything changed and as such, will not acknowledge anything has changed. All $scope.$apply does is basically says: “Hey Angular, a value changed, thought you should know, so you can tell your listener ($watchers) homies about it”.

Actions in AngularJS that trigger a $digest can include; in-built Angular directives like ng-repeat, ng-hide, ng-show, ng-click and even $http calls. If you try using $scope.$apply within one of these calls or even within a $timeout, you will get issues.
Classic scenario / example is updating scope in setTimeout function

setTimeout(function () {
    $scope.message = "Timeout called!";
    $scope.$apply();
}, 3000);

setTimeout(function () {
    $scope.$apply(function () {
        $scope.message = "Timeout called!";
    });
}, 3000);

$apply can be called in 2 ways

  • Without function
    $scope.$apply();
    
  • With function expression as parameter

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

So what’s the difference – The difference is that in the first version, we are updating the values outside the angular context so if that throws an error, Angular will never know. Now if you wrap inside the function call and that piece of code which updates scope throws exception, that exception will be handled by $exceptionHandler. Otherwise you will have to handle that exception yourself.

The only actually different between calling $apply(function() {}) with your code in the function body and calling $apply() after your code, is the exception handling.

Pseudo code for $apply with function

function $apply(expr) {
  try {
    return $eval(expr);
  } catch (e) {
    $exceptionHandler(e);
  } finally {
    $root.$digest();
  }
}

 

Scope’s $apply() method transitions through the following stages:

  1. The expression is executed using the $eval() method.
  2. Any exceptions from the execution of the expression are forwarded to the $exceptionHandler service.
  3. The watch listeners are fired immediately after the expression was executed using the $digest() method.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s