I'm working on a project that's using AngularJS v1.5.11 to display a large table of data -- it is a continuous build system which displays a table of rows for each change that comes in to source control. The columns are some data that's "static" like the information about the change, and some dynamic columns which show the current state of various automated builders/testers for that change. The page polls several different REST endpoints from a build server, and updates the page with current results from many different build machines.
I have made quite a few improvements to the page to add additional information, now I'm running in to performance issues due to too many watchers. Full-page digests happen frequently and the number of watchers is in the thousands, causing some interactive operations to have several seconds of delay.
I use the
:: ("one-time-binding") syntax already where applicable, but the heaviest use of watchers is in the columns which show the build/test results and those need to update as new data comes in. One-time-binding doesn't make sense in those cases.
I have already come up with a solution which involves disabling the watchers on old rows, since after a certain point we can guess that a particular row is not going to go get updated anymore (once all of the builders have moved on to processing a more recent change). I'm using something similar to this page, having a
suspendable directive which can remove the watchers from a row upon an event.
There are a couple problems I'm having with the approach of suspending watchers
- Sometimes those old rows do get new data contrary to our heuristic which deactivates the row, e.g. someone goes back and manually re-runs a build on an old change. Then that row fails to display the up-to-date data
- There are some interactive "ng-click" features that fail to work on rows that have been deactivated.
The other issue that I have is that currently the table is restricted to a limited number of rows, but I would like for it to automatically add rows when the user scrolls down ("infinite scrolling") so that they can view old data. This is going to dramatically increase the number of rows and thereby increase my performance issues with watchers.
Are there any other performance strategies that would help other than what I'm doing (one-time-binding and disabling watchers)?
How do others approach problems like this in Angular, or is Angular just not really well suited to this kind of a high-density information display? (A previous implementation of a similar page using jQuery runs much faster because once it adds a row, it pretty much leaves it alone, it just sits there in the DOM not incurring any extra cost each time new data comes in)
I realize I'm on an old version of Angular, and that Angular2 is supposed to be better for performance. What are the specific features in newer versions that might help with these issues?