Optimisation: idiomatic way to split DOM rendering?


#1

Consider the following:

  • server is returning a lot of data at once
  • pushing everything to the DOM in one go would take long and block the browser

Is there a recommended way to (manually) control Ember to:

  • render the first N elements
  • render next N elements in the following run loop
  • and so on

My initial thought was to put each DOM group update in an Ember.run.next. But according to the doc, “multiple operations scheduled with Ember.run.next will coalesce into the same later run loop”. So it won’t act as a “queue”.


#2

That’s a difficult task. How do you decide when to render everything fast or render portions etc. Although I’m unfamiliar with your particular situation, there is always Ember.run.later… You might consider decreasing the bound items, or using listview for your items that render out of view. Just some ideas.


#3

Wouldn’t scheduling for the next iteration result in the browser being blocked anyway? You’re basically rendering all the time in each run so I don’t think it makes a difference.

I would implement some lazy loading system. Either lazy render items into the DOM or, even better, lazy load them from the server when needed.


#4

Well technically scheduling something delayed gives the browser/any other javascript the opportunity to hop in and perform some action it was waiting to do. You can simulate the issue thingista is referring to by putting a gif on the page then starting a for loop that lasts for a few seconds doing nothing but writing to the console or something. Similarly you can watch other javascript scripts being blocked while waiting for another script to finish executing. Below you’d see world 9999999999 times, and probably for the next few minutes (purely a guess, jsbin kills off long loops like this) before you’d see the alert saying hello, despite us wainting that alert to happen in 1 ms.

  setTimeout(function(){ alert('hello');}, 1); // 1 ms say hello

  for(var i = 0;i<9999999999;i++){
     console.log('world');
  }

#5

Take a look at Ember.ListView for incremental rendering and DOM reuse.


#6

Yeah but I assumed thingista meant he didn’t want to block the UI for too long so the user can still interact with the application. In that case this kind of scheduling won’t help you.


#7

Thanks to all for your help. Just to clarify our scenario:

  • user makes a request and gets a “spinner”
  • results are sent back progressively from the server

The issue is the server has no “intelligence” and will sometimes return 1 or 2 results, and sometimes 20 at once. In the latter case, rendering becomes a problem. Yet, from a user experience standpoint, it would be fine to make things appear as if results were coming one after the other, with a bit of wait between each. In fact, it would be better than the current <>5 seconds lock we experience from time to time when dozens of results are rendered at once.

We could not make Ember.run.later work, and Listview would mean quite a lot of refactoring. So it looks like we will need to implement a kind of lazy loading or throttling technique.


#8

Ember.run.later actually gives the UI thread the chance to interject. If you are referring to just using Ember.run.later to render the entire thing then it’ll be worthless, cause you’ll block the UI thread then. But if he’s using Ember.run.later multiple times you give the UI multiple chances to break in.

Personally, I wouldn’t recommend trying this approach, it sounds like a major pain in the ass to maintain.


#9

Lazy Loading would be a decent way to go, I’d suggest using the arrayproxy. Or you could just use some good ol’ fashion Ember.run.later to slowly populate an Ember.Array which is the array that’s the model being visually represented.