Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a simple javascript loop as you seen below:

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

That toggle class of span in the page as below:

<span id="sample-span" style="color: orange;">Sample Text</span>
<input type="button" value="click to run" onclick="runCode()" />

<style>
span {
    color: blue;
}
.colorized {
    color: red;
}
</style>

The problem is that when the loop is running the page freezes and can't see that span color changes.

How can I solve this problem?

jsfiddle link

UPDATE

Dear all, console.log(new Date()); is just a sample, you assume that here is running heavy javascript procces.

like image 664
Rasool Ghafari Avatar asked Sep 27 '17 11:09

Rasool Ghafari


People also ask

How does for loop work in JavaScript?

A for loop repeats until a specified condition evaluates to false. The JavaScript for loop is similar to the Java and C for loop. When a for loop executes, the following occurs: The initializing expression initialExpression , if any, is executed.

What is the JavaScript loop?

JavaScript Loops are used to repeatedly run a block of code - until a certain condition is met. When developers talk about iteration or iterating over, say, an array, it is the same as looping.


2 Answers

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

like image 72
Manuel Otto Avatar answered Sep 20 '22 21:09

Manuel Otto


The problem with your code is that the javascript task queue executes all available code in your function before performing DOM manipulation. Meaning that the class toggle calls are registered, the loop is executed, then the toggles are executed successively so you cannot see the color change.

What you need to do is send the second part of your function to the end of the task queue like follows :

function runCode() {
    $("#sample-span").toggleClass("colorized");
    // allows the first toggle to execute and sends the loop and the second
    // toggle to the end of the task queue
    setTimeout(function() {
        for (var i = 0; i < 5000; i++) {
            console.log(new Date());
        }
        $("#sample-span").toggleClass("colorized");
    }, 0);
}

I have reduced the number of iteration to reduce the browser lock, you can still see the color change still.

like image 40
Ghassen Louhaichi Avatar answered Sep 20 '22 21:09

Ghassen Louhaichi