javascript - 在 While 循环中 setTimeout 不起作用

标签 javascript while-loop settimeout

我今年 11 岁,刚刚开始编程。我试图使用 while 循环,我希望它以 block 的形式显示答案,而不是一大块。所以我尝试使用 setTimeout 但它只会在一秒钟后显示第一行,然后立即将其余部分显示为一个大块。此外,它还会使用数字 9 作为临时变量,即使我不知道它来自哪里。提前致谢。

我想在代码中保留 while 循环,因为我正在学习如何使用它们,所以如果您可以在答案中保留 while 语句,那就太棒了!

这是我的代码:

<!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>

最佳答案

我明白你想做什么,但不幸的是它不会按照你的想法工作。

setTimeout() 不会暂停代码的其余部分,它只是说“在运行我体内的东西之前等待这段时间”,同时脚本的其余部分将保留嘎嘎地走着。因此,循环的每个步骤之间不会有一秒的延迟,而是一个接一个地运行整个集合,然后一秒钟后,所有的 setTimeouts 接一个接一个地触发。

在 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>

不过,作为练习,可以通过在单步执行循环时更改每个 setTimeout 的持续时间来组合 whilesetTimeout - 这样您就可以(几乎)同时启动所有 setTimeouts,但增加了每个 setTimeouts 在触发之前等待的时间。

但有一个问题:您需要每个 setTimeout 为 temp 使用不同的值。如果您尝试在一个函数中处理这一切,那么当第一个 setTimeout 触发时,while 循环已经在整个循环中递增了变量,因此每个 setTimeout 最终都会使用应该是最后一次迭代的值。 (您的代码中也遇到了同样的问题:这就是您在第一次迭代中看到“9”的原因。)

如果您尝试通过等待在 setTimeout 内增加变量来解决这个问题,那么您只会陷入无限循环,因为直到第一个 setTimeout 触发后才会发生第一个增量。所以这也不好。 (使用 while 时经常会发生无限循环,这就是为什么我在几乎任何情况下都避免使用它。)

您可以通过使用每次迭代所需的特定值调用第二个函数来解决此问题,并让该辅助函数使用自己的持续时间设置自己的超时:

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>

关于javascript - 在 While 循环中 setTimeout 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44486075/

相关文章:

javascript - ng click inside li <a> 元素在 ng-repeat 中不起作用

php - while 循环总是打印最后插入的行结果

java - 如何在满足条件后从循环中跳出

bash - 在脚本中使用 `until` 和 `/usr/bin/timeout`

c# - 为什么不调用 WebBrowser 控件中通过 setTimeout 方法调度的代码

node.js - setTimeout - JavaScript 堆内存不足

JavaScript 幻灯片无法按预期工作

javascript - 如何将带有 getter/setter 的 TypeScript 类实例转换为 JSON 以存储在 MySQL 数据库中

javascript - 如何在ajax页面上启用后退按钮

javascript - 在 for 循环中使用 setTimeout