AngularJs Apply

If you’re working on Angularjs apps and getting $digest in progress or similar errors time to time, it means that you still need to know more about AjngularJs apply functionality and syncing your asynchronous calls with AngularJs properly.

While $apply and $digest concept are described very well in AngularJs documents, here I just share my experiments. As a rule of thumb you rarely need to call $apply (and almost never $digest except special cases like unit testing). The common usage of $apply would be the time you need to sync external DOM events like XHR or 3rd party libraries with your AngularJs app. If you see you are calling $apply many time in your app here and there, in most cases there is something wrong with your code and you need to fix it.

What $apply does?

This is a very simple function that force AngularJs to run $digest and trigger all listeners and watchers about new changes in their scopes.

Proper usage:

This is how you would normally call this function:

1
2
3
$scope.$apply (function () {
    $scope.someVariable = 'changed';
});

And if you miss it your app is most probably does not get informed about changes and might cause out-of-sync model updates.

Why is there an error?

This error means you’ve tried to call $apply in a scope where another $apply is still in progress. It’s time to revise your code. for example this code would generate error:

1
2
3
4
5
$http.get (url).success (function (result) {
    $scope.$apply (function () {
      $scope.newValue = result;
    });
});

Because all AngularJs modules (in most cases) keep their changes inside $apply to keep it in sync. Meaning that the above ‘success’ call back would be called within $apply itself. You don’t need to (and you can’t) do that again.

When to call $apply?

Most of usual and common asynchronous DOM functionalities like window, timeout, Ajax calls and … are already provided as AngularJs modules and they in sync with it (ie. $window, $timeout, $http). But still there is some cases that you need to call this function.

Recently I was working on a project which is using AngularJs and Facebook API and because Facebook API library is asynchronous, I was having difficulties to keep them in sync. Obviously this is one of rare cases that you need to use $apply.

Let’s see this in a simple example, while this example could be in AngularJs way and not using $apply, but I just write it in the way that it needs to call $apply. (this example is not a good practice).

1
2
3
4
5
6
7
angularApp.controller ('ExampleCrtl', [$scope, function ($scope) {
    window.setTimeout (function () {
        $scope.$apply (function () {
            $scope.somethingChanged = "I'm changed";
        });
    }, 1000);
}]);

And just for clarification here is the same example in AngularJs way:

1
2
3
4
5
6
angularApp.controller ('ExampleCrtl', ['$scope', '$timeout', 
function ($scope, $timeout) {
    $timeout (function () {
        $scope.somethingChanged = "I'm changed";
    }, 1000);
}]);

References:



comments powered by Disqus

ABOUT BOYNUX bLOG

My notes and experiments with different technologies and tools. All information here is solely my personal thougths and does not relate to my employer's point of view in anyways.


FOLLOW BOYNUX FOR UPDATES AND BLOGS


FORK ME!

© Copyright 2012-2017