简体   繁体   中英

setTimeout in while loop crashes my browser

I was trying to move an image by adding to its .style.left and all that worked, until I tried to add a while cycle (to add until its left value is 90) and add setTimeout so that the movement is visible. Problem is that the HTML doesn't even load anymore and after a while it asks me to either Stop script or Continue - both of which help nothing and I am forced to kill the browser.

Here's the relevant code:

    function sprint(){
    button = parseInt(document.getElementById("azisButton").style.left.split("%")[0]);
    while(button<10){
        setTimeout(function(){
            button++;
            //console.log(button);
        }, 1000);
        //console.log("Tady");
    }
}

Why does it happen? Do I get into infinite loop, or something?

EDIT: Is there any way to do it some other, smart way?

You built an endless loop! button++ is incremented in your callback, but the callback is only executed when the loop ends, as JavaScript is single threaded.

这是一个无限循环,因为 Javascript 是单线程的,在 while 循环完成之前,您的任何回调都不会执行,这永远不会发生,因为按钮在回调执行之前不会递增。

The while construct is a synchronous operation. Therefore you're just adding to the heap till the browser runs out of memory. What you need is a self-invoking function.

Best way to imagine this is to think of setTimeout as an IOU or debt system. Imaging the task you made with the while loop as a basket. You're job is to write an IOU and place it in the basket as a "to do later" or "do this task when I'm done with the task of the while loop"

So as you iterate over the loop each setTimeout becomes a "to do later" IOU and the while loop goes to the next iteration. Since the incrementing task is in one of those "to do later" functions they never get executed because they are waiting for the while loop to finish first. Hence the infinite loop.

To fix this logic you have to break out of the loop all together and make your own loop logic using a self-invoking function:

var button = 0;

function next() {
  button++;
  if (button < 10) {
    setTimeout(next, 1000);
  }
}

next();

A good way to keep this strait in your head is to interchange the setTimeout with a console.log in your mind. With a console.log you expect the command to return immediately and move on. The function passed into setTimeout will wait till the parent function it is defined in to finish before calling the function you passed it. In the example above next() is called after the parent next() finishes.

function sprint(){
    button = parseInt(document.getElementById("azisButton").style.left.split("%")[0]);
    if(button > 90){
        // move button code here
        setTimeout(sprint, 1000);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM