One of the biggest bottlenecks in Angular 1.x is the $digest cycle. Essentially what the $digest cycle does is keeps track of two-way bindings, watchers and other parts of your Angular application that can be updated.
For example if you have a text field using an ng-model, whenever you type in a value into this field, it will trigger a $digest cycle causing Angular to update all watchers and bindings in the app to see if anything has changed. This is because of the lack of object.observe() in ECMAScript 5 (although it is in ECMAScript 2016 (ES7) and planned for Angular 2.0).
In version 1.3 of Angular, a native debounce feature was introduced which can be supplied to ngModelOptions.
Debounce, what?
What is a debounce you say? Essentially it is a delay which says, “Wait X amount of time and then do this action if an action is not already in progress” so in the instance of waiting for typing in a field for an email for example, you might want to put in a delay of 300 milliseconds so if a user stops typing and doesn’t resume within 300 milliseconds, an action will be fired which will trigger a $digest cycle.
As can be seen in the above linked Angular documentation on ngModelOptions there are a few Plunker examples showing debounce and selective updates on ng-model.
<div ng-controller="ExampleController">
<form name="userForm">
Name:
<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ debounce: 1000 }" />
<button ng-click="userForm.userName.$rollbackViewValue(); user.name=''">Clear</button><br />
</form>
<pre>user.name = </pre>
</div>
The above example taken from the Angular documentation shows that we are setting a debounce value of 1000 milliseconds which is 1 second. This is a considerable delay, but will prevent the input from repeatedly thrashing ng-model with many $digest cycles.
By using debounce on your input fields and anywhere else where an instant update is not required, you can increase the performance of your Angular apps quite substantially. Not only can you delay by time, but you can also delay when the action gets triggered. If you don’t want to update your ng-model on every keystroke, you can also update on blur as well.
A word of warning
If you set your debounce values too high, users will perceive your app as slow because you are artificially delaying the response and triggering of actions within your Angular application.
In most cases, a delay of 250 to 350 is acceptable and will not offer any overly noticeable slowness in your applications. Unless you need to set a higher value for whatever reason, keeping your debounce values below 350 will ensure your app is not only performant but still responsive.
Thanks, you saved my day.
I’m using debounce with delay of 300ms on an input field and making ajax request on input change. But whenever the request is in progress, user cannot type in the input box. This is a frustrating experience for user. Can you tell me what might be causing this and how can I fix this?
I had a model that was kind of freezing the view. I just used debounce with delay of 100ms and it turned the things way better. 100ms was the price to solve my problem.
Thank you.