I’m hitting a bit of a wall trying to push performance out of our Ember app here at Netflix.
One of the issues I’m having a hard time addressing is how to keep an {{#each}} from completely removing every element underneath itself and reprocessing it all. This has been really problematic for us because of the fact the many of the {{#each}} blocks have components underneath them that do a lot (graphs) and get re-processed everytime, even if they don’t always need to.
The life cycle looks a little like this:
- Get some array of data. (pushed into a property on the model/controller)
- Map the array to something appropriate (Mapping often includes some dynamism in the form of “getting” another property, so Ember.computed.map() doesn’t always work out).
- Sort the array (again, some potential for dynamism here, so Ember.computed.sort() doesn’t always save me)
- {{#each}} the array.
- Assign properties from the objects in the array (generally also arrays) to components (generally graphing components).
- Goto 1.
The problem is that everytime I get new data in, I’m unsure how to get the {{#each}} to update only what it has to. The lion’s share of computing time in the app at this point is utilized parsing HTML.
I’m not even sure how to solve this problem without some sort of dirty checking. Some scenario where I keep an array, and reconcile it against the incoming array based on some tracking key I’ve specified.
To be clear, the performance issues are apparent with less than 30 items in the outer each, so I’m not talking about a lot of rows. At least in the outer loop.
So the most specific question I can make out of this: Is there a way to reconcile changes and update only what has actually changed, and not completely re-render everything?
To give an example of what I need it to do, here is a bit in Angular (really, truly, honestly not trolling, this is a problem I need to solve!): http://jsbin.com/poxoku/1/edit?html,js,output
What you’ll see in that Angular example is I have a directive that simply shows when it was initialized, so you can see it’s not re-creating the directive (aka component in Ember) whenever the array is updated, so long as a tracked id matches (via track by in the ng-repeat clause).
How can I accomplish this same behavior in Ember?
Thanks in advance.