Rasool Ghafari
Rasool Ghafari

Reputation: 4258

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.

Upvotes: 6

Views: 8600

Answers (4)

M0nst3R
M0nst3R

Reputation: 5283

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.

Upvotes: 2

Manuel Otto
Manuel Otto

Reputation: 6540

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

Upvotes: 6

Radovan Skendzic
Radovan Skendzic

Reputation: 2999

It's because you are toggling class twice on a button click. If you want to change color of the span when it finishes then write: function runCode() { $("#sample-span").toggleClass("colorized"); for (var i = 0; i < 100000; i++) { console.log(new Date()); } }

Upvotes: -2

CD-jS
CD-jS

Reputation: 1119

What are you trying to actually do? If you want the text to be shown as red and then toggle back after a specified time what you're really looking for is a setTimeout.

  $("#sample-span").toggleClass("colorized");

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

Upvotes: 0

Related Questions