Skip to content Skip to sidebar Skip to footer

How To Do A Loop In Javascript That Doesn't Block The Ui?

I have some javascript on my page that takes a very long time to execute (between 10-30 seconds) The code basically look like that : //Iterate over all the elements in the array fo

Solution 1:

Create a variable and set it to the starting value for your counter.

Create a function that:

  1. Does whatever the body of the loop does
  2. Increments the counter
  3. Tests to see if the counter is still under the length and, if it is, calls the function again

At this point you will have functionality equivalent to what you have already.

To pause between each call of the function, and allow time for other functions to fire, replace the direct call to the function with a call to setTimeout and use the function as the first argument.

var counter = 0;
functioniterator () {
    //Complex stuff for each element
    counter++;
    if (counter < array.length) {
        setTimeout(iterator, 5);
    } 
}

Solution 2:

Javascript uses something called the "Event Loop". Basically, there is a single thread that executes the code for each event as it occurs.

There is a function called setTimeout that you can use to make your Javascript code run in a future iteration of the loop. One trick that some developers use to keep the UI responsive during a long-running Javascript task is to periodically invoke code to be run with a timeout of zero. This cause the code to execute almost immediately without locking the event loop.

For example, you could write

var i = 0;
setTimeout(myFunction, 0);

functionmyFunction() {
    // complex stuff for each element.
    i++;
    if (i < array.length)
        setTimeout(myFunction, 0);
}

Be aware that on modern browsers, as long as Javascript code is executing, the UI will be unresponsive. Some browsers will even pop up a message urging the user to kill the script; very bad!

Also, in modern browsers, there is a new feature called "Web Workers". Web Workers allow for Javascript code to be executed in a separate thread. You can create as many threads as you like, so consider using web workers as well if your task is easily parallelizable.

Solution 3:

If you need the browser to update the page in the middle of your JS code, you need to yield to the browser, e.g. with a setTimeout, in a continuation passing style:

function doStuff(i) {
    // do some stuff with index i
    if (i < array.length) {
        setTimeout(doStuff.bind(window, i + 1), 0);
    }
}

doStuff(0);

Solution 4:

I tend to do this kind of thing like so:

function doStuff(arr) {
  if (arr.length === 0) {
    // do whatever you need to do when you're done
    return;
  }

  // Do body of computation here// Or use setTimeout if your browser doesn't do setImmediatesetImmediate(function () { doStuff(arr.slice(1)); });
}

doStuff(actualArrayOfThings);

Basically, break your loop body up, and use recursion to run each part of the loop in order. It's pretty easy to break this out into a helper function, since the loop body itself is what varies. Something like:

function eachAsync(arr, body) {
  if (arr.length === 0) {
    // do whatever you need to do when you're done
    return;
  }

  body(arr[0]);

  setImmediate(function () { eachAsync(arr.slice(1), body); });
}

eachAsync(actualArrayOfThings, doStuff);

Solution 5:

If your task is to process data without interfering with the user interface you can use WebWorkers https://developer.mozilla.org/en/docs/Web/Guide/Performance/Using_web_workers

Note it's supported by modern browsers.

Post a Comment for "How To Do A Loop In Javascript That Doesn't Block The Ui?"