skip to Main Content

Let’s say I have an array of 10000 random integers. I want to while loop through it and add each number to a ul. The thing is, if I do something like this:

const myArray = [/* 10000 totally random integers! */];
let pos = 0;
while (pos < myArray.length) {
  document.getElementById("unorderedList").innerHTML += `<li>${pos}</li>`;
  pos++;
}
console.log("done!");

It freezes the whole window until it finishes, then it logs everything. How can I make it so the loop adds the number every iteration until it finishes instead of finishing the loop then printing everything?
Note: this hypothetical function also needs to interact with a Window created with window.open, so I don’t think I can use workers since that interacts with the DOM.

2

Answers


  1. You can use requestAnimationFrame.

    requestAnimationFrame is a JavaScript method used for smooth and
    efficient animations on the web.

    It schedules a provided function to run before the next repaint,
    ensuring optimal performance by syncing with the browser’s rendering
    cycle.

    Unlike alternatives like setTimeout, it adapts to the screen refresh
    rate, resulting in visually smoother animations and better resource
    utilization.

    It’s commonly used in animation loops for updating positions and redrawing scenes.

    I add sample code below.

    const myArray = new Array(10000).fill(0).map((_, index) => index);
    const batchSize = 30; //you can control speed by this variable
    let pos = 0;
    const unorderedList = document.getElementById("unorderedList");
    
    const updateDOM = () => {
      const fragment = document.createDocumentFragment();
    
      while (pos < myArray.length && fragment.children.length < batchSize) {
        const li = document.createElement('li');
        li.textContent = myArray[pos++];
        fragment.appendChild(li);
      }
    
      unorderedList.appendChild(fragment);
    
      pos < myArray.length ? requestAnimationFrame(updateDOM) : stop();
    };
    
    const start = () => requestAnimationFrame(updateDOM);
    const stop = () => console.log("done!");
    
    start();
    <div id="unorderedList"></div>
    Login or Signup to reply.
  2. Issue

    It is due to the browser being busy updating the DOM in each iteration of the loop, and the rendering process is blocking the script execution.

    Solution

    You can use requestAnimationFrame to break the loop into smaller chunks, which allows the browser to handle rendering between each chunk.

    const myArray = [/* 10000 totally random integers! */];
    let pos = 0;
    const chunkSize = 50; // adjust it according to your myArray size
    const ul = document.getElementById("unorderedList");
    
    function processArrayChunk() {
      const fragment = document.createDocumentFragment();
    
      for (let i = 0; i < chunkSize && pos < myArray.length; i++, pos++) {
        const li = document.createElement("li");
        li.textContent = myArray[pos];
        fragment.appendChild(li);
      }
    
      ul.appendChild(fragment);
    
      if (pos < myArray.length) {
        requestAnimationFrame(processArrayChunk);
      } else {
        console.log("done!");
      }
    }
    
    requestAnimationFrame(processArrayChunk);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search