

Delaying the $digest() cycle in AngularJS - aarongray
http://www.aaron-gray.com/delaying-the-digest-cycle-in-angularjs/

======
jhpriestley
Time spent in the digest cycle scales proportionally to the product of how
often a digest occurs, and how many watches there are - each should be roughly
proportional to the size of the application, for an overall quadratic
complexity. If watches trigger other watches then this also lengthens the
cycle, so the growth is actually more than quadratic in the size of the
application - as bad as cubic possibly, if most notifications between modules
are accomplished by one watch function setting variables for another watch
function to pick up.

Debouncing controls one of the terms - frequency of digest cycles - so the
complexity grows somewhere between linear and quadratic. The only scalable
solution is to minimize the use of watches. Fortunately, this is also a good
idea from a code quality standpoint - watches are an unstructured control flow
system, similar to GOTO, and should be avoided even if they were efficient.

~~~
aikah
> watches are an unstructured control flow system, similar to GOTO

Any callback is a GOTO. in fact, any function call in C like languages IS A
GOTO.

So i'm not sure what is the point of saying that.

$scope.$watch is at the center of angularjs architecture,there is no way to
avoid it.

And that's what makes angularJS awesome,seamless integration between the view
layer and other app layers,without a single explicit event handler
registration,mediator,observer,... (except for directives obviously). No JS
framework but angularjs does that,not even React that needs a 3rd party
library to integrate itself with a domain layer.

That's why angularjs is so easy to use and beats everything else.

~~~
voidr
> Any callback is a GOTO. in fact, any function call in C like languages IS A
> GOTO.

If a function call would be a GOTO, then you wouldn't have a stack trace to
look at in your debugger.

I'm not sure what is the point in replying to a comment you don't actually
understand.

Angular's data binding model has a lot of shortcomings:

    
    
        angular.module("app").controller("SomeController", function($scope) {
            setTimeout(function () {
                $scope.someVar = 'happy debugging';
            }, 500);
        });

~~~
aikah

        angular.module("app").controller("SomeController",   function($scope) {
            setTimeout(function () {
                $scope.someVar = 'happy debugging';
            }, 500);
        });
    
    

Your example is stupid

1/ you should use $timeout or you're just asking for troubles.If not then
$scope.$apply

2/ use named function expressions

Any async operation in angularjs needs to trigger a digest cycle,that's
angular 101. You cant use a framework without actually understanding how it
works at first place.

Your point is moot because you are using an example that is a mistake at best
, but more like a bad piece of code,in angularjs context.No serious angularjs
developper would do that mistake,especially when you are supposed to test that
piece of code,using a function you didnt inject in the controller.

------
hmottestad
I used debouncing inside a watch expression. Really useful.

Another performance trick.

If you use ng-hide/show to hide a long list, then make a dummy function that
takes the list and the variable for the ng-hide/show and only returns the list
when the ng-show is true. This way you don't spend valuable time rendering
something that will have css hidden.

~~~
likeclockwork
ng-if is also useful in these cases.

[https://docs.angularjs.org/api/ng/directive/ngIf](https://docs.angularjs.org/api/ng/directive/ngIf)

~~~
aarongray
Yeah, and the good thing about ng-if compared to ng-show is that it removes
the elements from DOM, rather than just hiding them, which is better for large
datasets.

~~~
likeclockwork
Also, maybe this isn't a common issue and would be solved by better designed
models but.. using an ng-repeat against a list with some heterogeneous data..
ng-if works well to show only the UI components that apply to the object in
question without rendering things for no reason and then hiding them.

For example if you have a list of objects where some particular action might
apply only to a portion of them.

~~~
aarongray
I like it. We have seen a significant difference in performance in holding
objects in our JS but not putting them in the DOM until the user needs to see
them. I think the more you can remove from the DOM, the better.

------
wnevets
I had no idea canceling a timeout like that was called debouncing.

~~~
angersock
It goes back to something we used to do in electronics, usually with a Schmitt
trigger. The idea was that even a good switch (say, a small contact switch or
the like) would create several extra pulses as its internal contacts bounced
against each other before settling when activated--hence the name: it removes
bounces. :)

Nowadays we can use _.debounce or _.throttle.

~~~
jaredmcateer
Note throttle and debounce are slightly different. Debounce will delay firing
until the event causing the timeout reset stops (or pre-fire on the first
event and then ignore all subsequent events until they stop for a given
interval,) where throttle will fire one event within a given interval no
matter how many events it receives (as long as it's >=1.)

