I am fetching huge list of people (1000) from server as an API call.
Based on data I have to render "cards" for each user, which will contain their name, picture, age etc.
But when I do that, browser gets stuck for a while till all the cards are rendered. Is there any way to tell browser that its not necessary to render everything at once, it can do so one by one, without crashing itself ?
I am fetching huge list of people (1000) from server as an API call.
Based on data I have to render "cards" for each user, which will contain their name, picture, age etc.
But when I do that, browser gets stuck for a while till all the cards are rendered. Is there any way to tell browser that its not necessary to render everything at once, it can do so one by one, without crashing itself ?
Share Improve this question asked Aug 12, 2014 at 13:53 Rahul PrasadRahul Prasad 8,2328 gold badges45 silver badges49 bronze badges 6-
2
use
setTimeout
adding smaller number of elements to the DOM at a time – Igor Commented Aug 12, 2014 at 13:55 - 1 Maybe just don't render 1000 cards to the screen? They won't be shown all at once anyway. – Bergi Commented Aug 12, 2014 at 14:24
- 1 @Bergi: 1000 is just a random number, question is about preventing unresponsiveness due to heavy DOM manipulations. – Rahul Prasad Commented Aug 12, 2014 at 16:46
- @RahulPrasad: It's not about the number. Don't render much more than what fits on the screen, and it won't be heavy processing. Pagination has a reason. – Bergi Commented Aug 12, 2014 at 16:55
- I remember this blog post from one of the guys working at Trello, where they improved the performance for boards with hundreds of cards (the example they use was a page rendering a board with 996 cards). In the end they divided the cards in chunks and render one chunk at a time. – Daniel J.G. Commented Aug 12, 2014 at 17:25
2 Answers
Reset to default 3Take a look here
If you add an element to the DOM, the page will be repainted. If you add 100 elements one by one, it will be repainted 100 times, and that's slow. Create a single container and add nodes for the items to it before appending it to your page.
var container = $('<div>');
$.each(items, function (index, itm) {
var el = $('<div>');
el.attr('id', ID_PREFIX + index);
el.html(createHtml(itm));
container.append(el);
});
$('#list-container').append(container);
Something like the above (using jQuery, but you can be fine with plain JS).
(of course createHtml
is an utility function you can define to get the markup for your item and items
is the array with your data)
That said, I agree with @Bergi above: do you really need to show all items at the same time? Could you set a scrolling view that populates as you scroll down?
Next thing you can do, use RactiveJs or React to efficiently manage data-binding.
There are a few options here. The best options are, as others have mentioned, not to render at all:
Use an "infinite scroll" technique to only render what you need. The basic idea is to remove DOM elements that go offscreen and add those that e onscreen by inspecting the scroll position.
Use a different user-driven pagination mechanism.
Barring that, you can get better performance by rendering all in one go, either through constructing and setting innerHTML
or by using a document fragment. But with 1000's of elements, you'll still get poor performance.
At this point, you probably want batch processing. This won't be faster, but it will free up the UI so that things aren't locked while you're rendering. A very basic batching approach might look like this:
// things to render
var items = [...];
var index = 0;
var batchSize = 100;
// time between batches, in ms
var batchInterval = 100;
function renderBatch(batch) {
// rendering logic here
}
function nextBatch() {
var batch = items.slice(index, index + batchSize);
renderBatch(batch);
index += batchSize;
if (index < items.length - 1) {
// Render the next batch after a given interval
setTimeout(nextBatch, batchInterval);
}
}
// kick off
nextBatch();
It's worth noting, though, that there are limits to this - rendering is a bottleneck, but every DOM element is going to impact client memory too. With 10s of 1000s of elements, things will be slow and unresponsive even after rendering is plete, because the memory usage is so high.