javascript loop freezes browser and can't see

2020-04-05 17:39发布

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.

4条回答
劳资没心,怎么记你
2楼-- · 2020-04-05 18:10

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

查看更多
甜甜的少女心
3楼-- · 2020-04-05 18:17

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.

查看更多
Rolldiameter
4楼-- · 2020-04-05 18:19

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()); } }

查看更多
我想做一个坏孩纸
5楼-- · 2020-04-05 18:20

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);
查看更多
登录 后发表回答