Rakesh Soni
Rakesh Soni

Reputation: 1333

how to convert json to html with maximum optimization

I have some json array Data which have hundred of objects with data structure similar to following

var json = [{"id":"123","name":"user"},{"id":"124","name":"user2"},{"id":"125","name":"user4"}]

I am creating dropdown using this data (ul and li) by using following function

var newhtml = $("<div/>");
json.forEach(function (e) {
  newhtml.append('<li>'+e.name+'</li>');
});
$('ul').append(newhtml.html());

This is working fine but the problem is if json data goes near thousand it slows down. I already googled and found few ways which includes:

Now my question is How to create html using json data with optimized way ?

Upvotes: 0

Views: 203

Answers (6)

Yordan Nikolov
Yordan Nikolov

Reputation: 2678

You can try to put the full list of li in DocumentFragment and after the loop finishes add it to the DOM. Another solution would be to hold the list of li in DocumentFragment and add it to the DOM in parts, for that case you have to check where is the scroller, something like a infiti-scroll, where new content is added when you reach the bottom of the page.

var fragment = document.createDocumentFragment()
json.forEach(function (e) {
    var li = document.createElement('li')
    li.innerText = e.name;
    fragment.appendChild(li)
}
ul.appendChild(fragment);

Example with scroll:

var next = 50;
var ul = document.getElementById('ul');
ul.addEventListener('scroll', function(ev) {
   var a = ev.target.scrollTop;
   var b = ev.target.scrollHeight - ev.target.clientHeight;

   if((a / b) > 0.9) {
      //add next part of li's to the ul
      var part = document.createDocumentFragment();
      var start = next;
      next += next;
      [].slice.call(fragment.children, start, next).map(function(li) { part.appendChild(li); });
      ul.appendChild(part)
   }
});

Upvotes: 1

THEtheChad
THEtheChad

Reputation: 2432

It will be faster if you don't create the elements until the end. Create the raw HTML first and generate the elements last.

var list = json.map(function(user){
  return '<li>' + user.name + '</li>';
});

$('<div/>').html( list.join('') ).appendTo('ul');

As @Kannan J pointed out, it's even faster if you skip the join.

var html = json.reduce(function(str, user){
  return str += '<li>' + user.name + '</li>';
}, '');

$('<div/>').html( html ).appendTo('ul');

Upvotes: 5

Alexandru Severin
Alexandru Severin

Reputation: 6228

Whenever speed is an issue:

  1. Use simple for loops instead of forEach

  2. Don't concatenate strings with + in loops. Instead, add items to an array and join them

Example:

var newHtml = [];
for(var j=0, jsonLen=json.length; j<jsonLen; j++){
    newHtml.push('<li>'+json[j].name+'</li>')
}
$('ul').append(newHtml.join(''));

From my test, its about 6x faster than your solution. For 10.000 items, duration was reduced from 453ms to 77ms. (demo)

However, as Alex K. suggested, you should avoid generating thousand elements at once. Besides the performance issue its not user-friendly either. I recommend finding another solution such as generating elements while user scrolls or making him use a search/autocomplete function.

Upvotes: 0

Kannan J
Kannan J

Reputation: 508

Iterate once, add to simple string and insert one shot

var options = "";
for (var i = 0 ; i < json.length; i++) {
   options += "<li>" + json[i].name + "</li>"
}
$('ul').append(options);

Upvotes: 0

Alex K.
Alex K.

Reputation: 175816

Another option - building HTML then updating the DOM once:

var buffer = []
$.each(json, function(key, value) {
  buffer.push('<li>' + value.name + '</li>');
});
$('ul').append(buffer.join(""));

Upvotes: 0

degr
degr

Reputation: 1565

this way

var json = [];
var length = 100000;
while(length--){
   json.push({id: length, name: length});
}
var time = new Date().getTime();
var dropdown = document.createElement('select');
json.forEach(function(item){
    var option = document.createElement('option');
    option.innerHTML = item.name;
    option.value = item.id;
    dropdown.appendChild(option);
})
console.log(new Date().getTime() - time)

As I see 100000 elements take less than 2 sec, 10000 around 180 mcs

Upvotes: 0

Related Questions