When I first started looking at front end frameworks, all anyone wanted to talk about when it came to AngularJS was two-way data binding. You just connect the Model and the View and when one changes, so does the other. It's magic!

It's one of the more glittery feature of AngularJS, and at times it can be extremely useful. But, what's the cost? There's always a cost. With data-binding, the (potential) cost is a drop in performance.

Let's talk briefly about how AngularJS manages the data binding. If you've been coding in JavaScript for very long, you're probably familiar with the idea of an event loop. It would take a few very long blog posts (or a video) to accurately describe an event loop, but basically it works like this. Behind the JavaScript curtain, there's somewhat of a queue. This queue is waiting for events. JavaScript goes through the queue and tries to execute all the events. When it gets to the bottom of the queue, it goes right back up to the top and repeats the process. So when an event is added to the queue, it will get executed on the next loop around. AngularJS has an event loop that it calls the $digest loop that works more or less the same.

Any time you set up a data-binding, it adds a function to what's called the $watch list. And this $watch list gets resolved in the $digest loop. So the more data-bindings you've got in your app, the longer your $digest loop. There are many more moving parts to the way AngularJS implements the $digest loop, but the point remains the same. You may not see the performance effects when implementing a to-do list in an AngularJS tutorial, but if you're working on an application at scale, the data-bindings can really start to pile up.

But don't worry, it's manageable! There are many things you can do to keep your data binding woes under control, but here are two strategies I find very effective.

Bind Once

Often you need to render some data on the DOM that comes from a Model, but once it's been rendered it is completely static. There is no way for the user to modify the data in the View, and the Model won't be changing so you don't need to update the View. As of version 1.3 of AngularJS, there's a very handy feature available that allows us to render data without binding it back to the model. This means no function is added to the $watch list and therefor we can keep our $digest loop nice and small. Let's check it out.

Typically, you would render a value in the DOM like so:

<div>{{ user.name }}</div>

To handle this without the data-binding, simply update the code as follows:

    <div>{{ ::user.name }}</div>

How easy is that? AngularJS will process the DOM like normal, but then remove the binding from the $watch list and you're left with static content and a happy $digest loop. Those two little colons can help keep your data-binding overhead very minimal.

Control your ng-repeats

Maybe the biggest offender of overloading the $digest loop is ng-repeat. It automatically adds at least one binding for every item in the list, not including any additional data-bindings we might set up on those items. Consider this code:

    <ul>
      <li ng-repeat="friend in friends">
        <div ng-show="friend.attractive">Hot: {{ friend.name }}</div>
        <div ng-show="!friend.attractive">Not: {{ friend.name }}</div>
      </li>
    </ul>

In addition to being a shallow jerk that categorizes his friends attractiveness, we've also got 5 data-bindings set up for each item in the list. Imagine a list of 200 friends, that's 1000 data-bindings! And this is still a relatively simple ng-repeat implementation; it can certainly get much more complex. I've read that AngularJS starts to slow down at about 2000 data-bindings, which is not to difficult to achieve.

So how do we keep our ng-repeats under control? We must be mindful of how many data-bindings we are setting up for each item. If you need to do some DOM manipulation (such as show/hide), consider doing it inside the link function of a directive using Jquery style DOM selectors and manipulations (.show()/.hide()). If you absolutely must have a lot of data-binding handled in an ng-repeat, you might have to break up the size of the list with pagination, smart infinite scrolling, etc...

To summarize, it pays to be mindful of where you're implementing data-binding. Keep it on your mind as you are building your application. Ask yourself if it's really necessary for that feature you're working on to utilize data-binding. I know we've identified many areas of our application where the data-bindings are not necessary, and I bet you do to.

Happy optimizing!

Mark Curphey, Vice President, Strategy Mark Curphey is the Vice President of Strategy at CA Veracode. Mark is the founder and CEO of SourceClear, a software composition analysis solution designed for DevSecOps, which was acquired by CA Technologies in 2018. In 2001, he founded the Open Web Application Security Project (OWASP), a non-profit organization known for its Top 10 list of Most Critical Web Application Security Risks. Mark moved to the U.S. in 2000 to join Internet Security Systems (acquired by IBM), and later held roles including director of information security at Charles Schwab, vice president of professional services at Foundstone (acquired by McAfee), and principal group program manager, developer division, at Microsoft. Born in the UK, Mark received his B.Eng, Mechanical Engineering from the University of Brighton, and his Masters in Information Security from Royal Holloway, University of London. In his spare time, he enjoys traveling, and cycling.

Love to learn about Application Security?

Get all the latest news, tips and articles delivered right to your inbox.

 

 

 

contact menu