How to Stop Intense JavaScript Loop from Freezing the Browser

How to stop intense Javascript loop from freezing the browser

I would ditch the "each" function in favour of a for loop since it is faster. I would also add some waits using the "setTimeout" but only every so often and only if needed. You don't want to wait for 5ms each time because then processing 3500 records would take approx 17.5 seconds.

Below is an example using a for loop that processes 100 records (you can tweak that) at 5 ms intervals which gives a 175 ms overhead.

var xmlElements = $(xmlDoc).find('Object');
var length = xmlElements.length;
var index = 0;
var process = function() {
for (; index < length; index++) {
var toProcess = xmlElements[index];
// Perform xml processing
if (index + 1 < length && index % 100 == 0) {
setTimeout(process, 5);
}
}
};
process();

I would also benchmark the different parts of the xml processing to see if there is a bottleneck somewhere that may be fixed. You can benchmark in firefox using firebug's profiler and by writing out to the console like this:

// start benchmark
var t = new Date();
// some xml processing
console.log("Time to process: " + new Date() - t + "ms");

Hope this helps.

How to avoid freezing the browser when doing long-running computations in Javascript

If you only need to do a calculation and don't need to access the DOM during the long running calculation, then you have two options:

  1. You can break the calculation up into pieces and do a piece at a time on a setTimeout(). On each setTimeout() call, the browser will be free to serve other events and will keep the page alive and responive. When you finish the last piece of the calculation, you can then carry out the result.
  2. You can run the calculation in the background using a webworker in modern browsers. When the calcuation is done in the webworker, it sends a message back to the main thread and you can then update the DOM with the result.

Here's a related answer that also shows an example: Best way to iterate over an array without blocking the UI

How to rewrite forEach to use Promises to stop freezing browsers?

The answer you reference is right, you need setTimeout. Using a promise-chain alone wont help because .then chains execute on a microtask queue, which in most browsers are emptied completely at the tail of the current run-to-completion. In other words, they'll still freeze things.

If you want something ES6-y, I rely on this trusty helper:

var wait = ms => new Promise(resolve => setTimeout(resolve, ms));

Then I can do this:

longArray.reduce((p, i) => p.then(() => doIntensiveStuff(i)).then(() => wait(5)),
Promise.resolve());

Unless you can use workers of course.

javascript loop freezes browser and can't see change before loop

You have to add a small delay after changing the color before running the heavy process:

function runCode() {
$("#sample-span").toggleClass("colorized");
setTimeout(runTask,10)
}

function runTask(){
for (var i = 0; i < 100000; i++) {
console.log(new Date());
}
$("#sample-span").toggleClass("colorized");
}

JSFiddle

How to process the big loop without freezing the browser using setTimeOut function in javascript?

You can use a loop variable, like the following code. In this example, the function increases every element by 1. The timeout period is 1 millisecond.

    var currentIndex;
function processNthElement(array) {
if (currentIndex >= array.length)
{
//the whole array has been processed, do what you need to do
//with the results here
return;
}

//do what you want with the array element here
array[currentIndex]++;

currentIndex++;

setTimeout(function () {
processNthElement(array);
}, 1);
}
function processArrayWithSetTimeout(array) {
currentIndex = 0;
processNthElement(array);
}

Then to process a large array, just call processArrayWithSetTimeout(array). However since we are using timeout, you need to process the result at the very last function call(see the comment in the function). If an array has 10000 elements, it will take more than 10000 milliseconds or 10 seconds to process, but the UI won't be freezed.

Note that this still processes the array sequentially but without freezing the UI as it waits for a while after processing 1 element.

How do I loop through this mysql array without freezing the website

I guess I should answer this question if anyone else ends up stumbling onto the same issue.

I change the foreach loop slightly by adding the ID as a data-id to the options

foreach($names_array as $value) {
echo "<option data-id='".$value['names_id']"'>".$value['names_name']."</option>";
}

Through js (and jquery) you can obtain the id of the chosen student like this:

currentVal = $("#inputID").val();
currentID = $("#listID option[value='" + currentVal + "']".attr('data-id');

now you can find the index of the chosen student in the namesArray doing this:

if (currentID != undefined || currentVal != "" || currentVal != " ") {
arrayIndex = namesArray.findIndex(x => x.names_id == currentID);
currentArray = namesArray[arrayIndex];
}

where namesArray is the var 'names' json parsed which I echo in the script seen in the question and the if block prevents it from even checking the array if the id is undefined or the input is empty.

Why is my browser freezing while doing a counting for child elements inside a container div using jQuery?

I've tried with the sample page:

http://thegrubbsian.github.io/jquery.ganttView/example/index.html

and the script that you posted doesn't showed any problem (these are only 17 childs). Generally I've used jQuery to retrieve list of thousand or ten thousands elements without any problem. Are you really sure that it's this line to freeze your browser ? try placing a return in the line below to be sure that the problem is not some place after this call.

Generally working with the DOM is slow but not so slow that you can feel an operation like retrieving 500 elements. A simple way to speedup it is to store those elements when you draw it or to infer them from your starting data. They are number of elements that you passed to jQuery Gantt to draw and count those javascript elements is way faster than parsing the generated DOM. Try posting your code and we can help you about this.

Last test, I've never done a benchmark maybe this is faster:

$('.ganttview-block').length

Hope this helps



Related Topics



Leave a reply



Submit