Reputation: 1333
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:
li
to ul
every time. So I append only once after forEach
loop. It optimize things to not that much. Now my question is How to create html using json data with optimized way ?
Upvotes: 0
Views: 203
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
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
Reputation: 6228
Whenever speed is an issue:
Use simple for
loops instead of forEach
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
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
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
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