简体   繁体   English

在While循环中setTimeout不起作用

[英]In a While loop setTimeout not working

I am 11 and just started programming. 我11岁,刚刚开始编程。 I was trying to use a while loop and I want it to display the answers in blocks instead of one huge chunk. 我试图使用while循环,但我希望它以块而不是一个大块的形式显示答案。 So i tried to use a setTimeout but it would just display the first line after a second then instantly display the rest as a huge chunk. 因此,我尝试使用setTimeout,但是它只会在一秒钟后显示第一行,然后立即将其余部分显示为一个巨大的块。 Also it would then use the number 9 as the temp variable even though i got no idea where that came from.Thanks in advance. 即使我不知道那是哪里来的,它也会使用数字9作为临时变量。

I would like to keep the while loop in the code because I am learning how to use them , so if you could keep the while statement in your answer that would be awesome! 我想在代码中保留while循环,因为我正在学习如何使用它们 ,因此,如果您可以将while语句保留在答案中,那就太好了!

here is my code: 这是我的代码:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Made with Thimble</title>
    <link rel="stylesheet">
</head>

<body bgcolor="lightblue">
    <div id="d2">
        Divisible by 2
    </div>
    <div id="d3">
        Divisible by 3
    </div>
    <div>
        <input id="seed" type="number" placeholder="seed" value="3"><br>
        <input id="max" type="number" placeholder="max" value="8">
    </div>
    <button onclick="count()">Count</button>
    <div id="output"></div>
    <script>
    function count() {

        var seed = document.getElementById("seed").value
        var max = document.getElementById("max").value
        var temp = 1
        var output = document.getElementById("output")
        temp = seed
        console.log("seed:" + seed)
        console.log("max:" + max)
        document.getElementById("output").innerHTML = " "
        while (temp <= max) {

            var intdivby2 = temp % 2
            var intdivby3 = temp % 3

            setTimeout(function() {
                document.getElementById("output").innerHTML += "remainder of " + temp + " divided 
                by 2 is: "+intdivby2.toString()+" < br > "
                document.getElementById("output").innerHTML += "remainder of " + temp + " divided 
                by 3 is: "+intdivby3.toString()+" < br > "
                temp++
            }, 1000)

        }
    }
    </script>
</body>
</html>

Mixing loops with timeouts is a bad idea, instead use an interval and delete it when the condition is no longer true 将循环与超时混合是一个坏主意,而是使用间隔并在条件不再成立时将其删除

var intervalId = setInterval(function () {
    var intdivby2 = temp % 2;
    var intdivby3 = temp % 3;
    document.getElementById("output").innerHTML += "remainder of " + temp + " divided by 2 is: " + intdivby2.toString() + " <br/> ";
    document.getElementById("output").innerHTML += "remainder of " + temp + " divided by 3 is: " + intdivby3.toString() + " <br/> ";
    if (++temp > max) clearInterval(intervalId);
}, 1000);

Small Example 小例子

 var index = 0; var intervalId = setInterval(function() { var text = "Iteration: " + index + "<br/>"; document.getElementById("output").innerHTML += text; if (++index > 10) clearInterval(intervalId); }, 1000); 
 #output { max-height: calc(100vh - 130px); overflow: auto; } 
 <div id="output"></div> 

Another way would be to use recursive timeouts 另一种方法是使用递归超时

(function asyncLoop() {
    setTimeout(function () {
        var intdivby2 = temp % 2;
        var intdivby3 = temp % 3;
        document.getElementById("output").innerHTML += "remainder of " + temp + " divided by 2 is: " + intdivby2.toString() + " <br/>";
        document.getElementById("output").innerHTML += "remainder of " + temp + " divided by 3 is: " + intdivby3.toString() + " <br/>";
        if (++temp <= max) asyncLoop();
    }, 1000);
})();

Small Example 小例子

 var index = 0; (function asyncLoop() { setTimeout(function() { var text = "Iteration: " + index + "<br/>"; document.getElementById("output").innerHTML += text; if (++index <= 10) asyncLoop(); }, 1000); })(); 
 #output { max-height: calc(100vh - 130px); overflow: auto; } 
 <div id="output"></div> 

I see what you're trying to do there, but unfortunately it won't work the way you're thinking. 我知道您在尝试做什么,但是不幸的是,它无法按照您的想法工作。

A setTimeout() doesn't pause the rest of your code, it simply says "wait this amount of time before running the stuff inside me", and meanwhile the rest of the script will keep chugging along. setTimeout()不会暂停其余的代码,它只是说“等待这段时间,然后再运行我内部的东西”,与此同时,脚本的其余部分将不断变化。 So instead of a one second delay between each step of the loop, your loop runs through its entire set one right after another, then one second later all of your setTimeouts fire one right after another. 因此,与循环的每一步之间没有一秒的延迟相比,循环使整个循环一次接一个地运行,然后一秒钟之后,所有setTimeouts依次触发。

A more typical way in javascript to do what you want (cause a chunk of code to run repeatedly with a delay between each repetition) is setInterval() -- it works almost exactly like setTimeout() except that it keeps firing every time the interval expires (until you cancel it with clearInterval() .) For example: javascript中一种更典型的方式来执行您想要的操作(导致一大段代码在每次重复之间都有延迟地重复运行)是setInterval() -它几乎与setTimeout()除了它每次间隔触发一次过期(直到使用clearInterval()取消它为止。)例如:

 function count() { var seed = document.getElementById("seed").value var max = document.getElementById("max").value var temp = 1 var output = document.getElementById("output") temp = seed // you already captured the "output" node, so we can reuse it here (and below). output.innerHTML = " " var theInterval = setInterval(function() { var intdivby2 = temp % 2 var intdivby3 = temp % 3 // no need to call .toString() on these vars; the fact that we're // adding them to another string will cause that to happen automatically output.innerHTML += "remainder of " + temp + " divided by 2 is: "+intdivby2+" <br> " output.innerHTML += "remainder of " + temp + " divided by 3 is: "+intdivby3+" <br> " temp++ if (temp > max) { clearInterval(theInterval); // this stops the loop } }, 1000); } 
 <div> <input id="seed" type="number" placeholder="seed" value="3"><br> <input id="max" type="number" placeholder="max" value="8"> </div> <button onclick="count()">Count</button> <div id="output"></div> 

Just as an exercise, though, it is possible to combine while and setTimeout by changing the duration of each setTimeout as you step through the loop -- this way you're starting up all the setTimeouts simultaneously (almost), but increasing the amount of time each one waits before it fires. 但是,就像练习一样,可以通过在循环过程中更改每个setTimeout的持续时间来组合whilesetTimeout -这样,您可以同时(几乎)启动所有setTimeouts,但是会增加每个人等待射击的时间。

But there's a catch: you need each setTimeout to use different values for temp . 但是有一个陷阱:您需要每个setTimeout为temp使用不同的值。 If you try to handle this all in one function, by the time the first setTimeout fires, the while loop has already incremented the variables all the way through the loop, so every setTimeout ends up using the value from what should have been the last iteration. 如果您尝试在一个函数中处理所有这些问题,那么在第一个setTimeout触发时,while循环已经在循环中一直增加了变量,因此每个setTimeout最终都使用上次迭代中的值。 (You had this same problem in your code, too: that's why you were seeing '9' on the first iteration.) (您的代码中也遇到了同样的问题:这就是为什么您在第一次迭代中看到“ 9”的原因。)

If you try to solve that by waiting to increment the variables until inside the setTimeout, you just wind up with an endless loop, because the first increment doesn't happen until the first setTimeout fires. 如果您尝试通过等待直到在setTimeout内递增变量来解决该问题,那么您将陷入无限循环,因为直到第一个setTimeout触发时才会发生第一次递增。 So that's no good either. 所以那也不好。 (Endless loops are often what happens when you use while , which is why I avoid using it under pretty much any circumstances.) (当您使用while ,经常会发生无尽循环,这就是为什么我避免在几乎任何情况下都使用它的原因。)

You can solve this by instead calling a second function with the specific values you need for each iteration, and having that secondary function set up its own timeout with its own duration: 您可以通过以下方法解决此问题:改为使用每个迭代所需的特定值调用第二个函数,并使该第二个函数设置自己的超时时间和持续时间:

 function count() { var seed = document.getElementById("seed").value var max = document.getElementById("max").value var temp = seed var i = 1 // or use 0 to have the first iteration fire immediately while (temp <= max) { handleIteration(temp, i); temp++ i++ } } function handleIteration(temp, i) { // temp and i are safely scoped within this function now, we don't // need to worry about the while loop changing them setTimeout(function() { var intdivby2 = temp % 2 var intdivby3 = temp % 3 var output = document.getElementById('output') output.innerHTML += "remainder of " + temp + " divided by 2 is: " + intdivby2 + " <br> " output.innerHTML += "remainder of " + temp + " divided by 3 is: " + intdivby3 + " <br> " }, i * 1000) // <-- changes the duration of the timeout } 
 <div> <input id="seed" type="number" placeholder="seed" value="3"><br> <input id="max" type="number" placeholder="max" value="8"> </div> <button onclick="count()">Count</button> <div id="output"></div> 

Asynchronous while loop ( due to some awesome ES7 stuff (just the newest browsers support it)): 异步while循环(由于一些很棒的ES7东西(只是最新的浏览器支持它)):

function timer(t){
  return new Promise(r=>setTimeout(r,t));
}

async function main(){
  var a=0;
  while(a<10){
    alert(a);
    a+=1;
    await timer(1000);//wait one second
  }
}
main();

Your code does not work because setTimeout does not stop the current functioj from executing. 您的代码不起作用,因为setTimeout不会停止当前函数的执行。 It will start a timer in the background, and it will then push the passed function onto the so called qeue , wich is executed when the main thread stops. 它将在后台启动计时器,然后将传递的函数推入所谓的qeue ,这将在主线程停止时执行。

var a=true;
while(a){
 setTimeout(_=> a=false,1000);
 //will run forever as a is never set to false
}
//the main code would exit here and the timers are somewhen executed
//unreachable point were a=false...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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