In big projects, we have many features with many parts of view.
$apply start refreshing the entire page by calling all of the dirty-checking algorythms and then update the DOM elements. Fine, DOM is not modified if it's unnecessary. But calling all of these algos can take lots of time.
Instead of calling
$apply everytime, it's possible to use
$digest to refresh a specific
$scope. Ok so it's possible to call just the algos we wants for specific features instead of the big page.
The first problem:
All of the AngularJS behaviors are based on calling $apply, when the user click buttons, with XHR requests, etc. Unless you want to re-code all of these features, $apply will be called many many times.
In my point of view, the developer should have the control of which features he want to $digest instead of the whole page. It's the basic of a complicated UI with lots of components. Actually it's not possible to have a big project in a single page with many features with AngularJS. This is problematic because AngularJS is designed for this use. Try using Drag&Drop with many components, it's the end of the world.
My simple example:
We have 3 features. We just want to $digest "Feature A" and "Feature C" when user interacts with "Feature A". With a simple ng-click it's not possible because it calls $apply that calls $digest of "Feature B".
With a classic button (jQuery click event) we can $digest "Feature A" then with a Service $digest "Feature C".
The second problem:
One of the main rules of AngularJS is to prevent the start of a second $digest in the first one. For the $apply process it's quite understandable, fine. But for a second independant $digest called by the first, why stop this behavior?
Example:
Once again, we want to refresh just two features ("A" and "C") of the page. But this time, just after the user has changed a value in the view (on "Feature A"). We don't use ng-model because it calls $apply. For the example we're just using jQuery to observe input changes and update the $scope. The focus of the example is within a $watch. After the value has changed, we want to share this value with the "Feature C". Problem, in a $watch we already are in a $digest. AngularJS will break if we are calling a second $digest, so the "Feature C" can't call $digest directly. The only way is to use a setTimeout() to refresh the feature asynchronously, after the $digest ($timeout() calls $apply). With this solution, we can have lots of latencies depending on algos sizes. Try with a D&D for example.
ConclusionMe and my team are actually creating an IDE webservice. We are using AngularJS since version 1.0.4. and we feel its strength every day. I already have posted an issue in the community found inside our devs (
Digest ng-repeat after manual DOM manipulation causes disorganized list).
This is a big project containing a central page with many features (like Solution explorer, toolboxes, etc.). It's not possible to refresh the entire page with
$apply everytime. We need to refresh just parts of the UI and it's okay because we are the developers and have the control of these.
$apply is not designed for big projects.
So, maybe I'm wrong but I think we really need to change the behavior of AngularJS dirty-checking updates. We need to use $digest most of the time and
$apply rarely. For me, ng-click should call the
$digest of the current scope and not for the
$rootScope, like all of the ng- directives and
$http, ectc.