Reputation: 3373
How to render this with "Stop Scripting Dialog". Any solution can be appreciated. Thanks in advance
document.write("<ul>");
for(var i=0;i<1000000;i++){
document.write("<li>");
document.write("<div><input value='"+i+"'/></div>");
document.write("</li>");
}
document.write("</ul>");
Upvotes: 1
Views: 1336
Reputation: 691
When ever javascript updates a DOM object, the browser would have to render the page again; in your case it would be 1 million times. This is guranteed to slow down even the fastest machines.
Avoid that by generating the HTML as many time as you like, but only asking the browser to render it once.
var list;
for (var i = 0; i < 1000000; i++) {
list += "<li><div><input value='" + i + "'/></div></li>";
}
document.write("<ul>"+list+"</ul>");
Upvotes: 0
Reputation: 707238
First off, I will assume this is a theoretical discussion because no page design should ever contemplate multiple millions of DOM elements. If ever it was thought there could be this many elements, then a different design that involves showing smaller windows of the data at a time should be worked out.
To get around the unresponsive dialog, you have to break your javascript process into pieces and execute each piece separately while allowing the system to process other events between pieces. This is normally done by breaking the work into chunks and then executing each chunk on a setTimeout()
. You can see several examples of processing a large array here:
Best way to iterate over an array without blocking the UI.
But, you have a number of issues with this test because you will also have to stop using document.write()
because once you're letting the system processing other events between setTimeout()
operations, you can no longer use document.write()
to insert new elements in the parsing stream because the document will finish parsing. Instead, you would have to change to dynamically insert the DOM elements at the appropriate place in the DOM.
Here's some code:
function insertElements(num) {
var totalCntr = 0;
var chunkSize = 1000;
var parent = document.getElementById("container");
var progress = document.getElementById("progressCntr");
function doChunk() {
var chunkCntr = 0;
var fragment = document.createDocumentFragment();
while (chunkCntr < chunkSize && totalCntr < num) {
var li = document.createElement("li");
li.innerHTML = "<div><input value='" + totalCntr + "'/></div>";
fragment.appendChild(li);
++totalCntr;
++chunkCntr;
}
parent.appendChild(fragment);
progress.innerHTML = totalCntr;
if (totalCntr < num) {
setTimeout(doChunk, 0);
}
}
// start the whole thing
doChunk();
}
insertElements(100000);
Working demo: http://jsfiddle.net/jfriend00/0vw82q5y/
This is currently set to 100,000 elements. If you want to experiment with higher values, you are welcome to (subject to the memory limits of your system).
The system will be more responsive to user input while this is running if you decrease the chunkSize
value. The overall end-to-end time will probably get faster if you increase the chunksize
value.
If each chunk could be it's own DOM tree such that it could be inserted in one single DOM operation, then the end-to-end time here would be faster. That is not possible if you're inserted all <li>
elements though. The use of a document fragment here tries to help with this issue, but in the end, it still has to insert each <li>
into the document on it's own which really does slow down this operation.
Note: breaking the work into chunks may slow the overall end-to-end performance down. I have not tried to optimize the performance of this code, but rather wanted to illustrate the concept.
Upvotes: 5