在 While 循环中 setTimeout 不起作用 [英] In a While loop setTimeout not working

查看:66
本文介绍了在 While 循环中 setTimeout 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

这是我的代码:

<头><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>用顶针制作</title><link rel="样式表"><body bgcolor="lightblue"><div id="d2">可被 2 整除

<div id="d3">可被 3 整除

<div><input id="seed" type="number" placeholder="seed" value="3"><br><input id="max" type="number" placeholder="max" value="8">

<button onclick="count()">Count</button><div id="输出"></div><脚本>函数计数(){var seed = document.getElementById("seed").valuevar max = document.getElementById("max").value变量温度 = 1var output = document.getElementById("输出")温度 = 种子console.log("种子:" + 种子)console.log("max:" + max)document.getElementById("output").innerHTML = " "而(温度 <= 最大值){var intdivby2 = 温度 % 2var intdivby3 = 温度 % 3设置超时(函数(){document.getElementById("output").innerHTML += "" + temp + " 的剩余部分by 2 是:"+intdivby2.toString()+" <>"document.getElementById("output").innerHTML += "" + temp + " 的剩余部分by 3 是:"+intdivby3.toString()+" <>"温度++}, 1000)}}</html>

解决方案

我明白你想在那里做什么,但不幸的是它不会像你想的那样工作.

A setTimeout() 不会暂停其余的代码,它只是说在运行我内部的东西之前等待这段时间",同时脚本的其余部分将保持一路狂奔.因此,不是在循环的每一步之间延迟一秒,而是你的循环一个接一个地运行整个集合,然后一秒后你的所有 setTimeouts 一个接一个地触发.

javascript 中一种更典型的方式来做你想做的事情(导致一段代码重复运行,每次重复之间有延迟)是 setInterval() -- 它的工作方式几乎与 setTimeout() 除了它每次间隔到期时都会继续触发(直到您使用 clearInterval() 取消它.)例如:

function count() {var seed = document.getElementById("seed").valuevar max = document.getElementById("max").value变量温度 = 1var output = document.getElementById("输出")温度 = 种子//你已经捕获了输出"节点,所以我们可以在这里(和下面)重用它.output.innerHTML = " "var theInterval = setInterval(function() {var intdivby2 = 温度 % 2var intdivby3 = 温度 % 3//不需要在这些变量上调用 .toString();我们是//将它们添加到另一个字符串将导致自动发生output.innerHTML += "" + temp + " 的余数除以 2 是: "+intdivby2+" <br> "output.innerHTML += "" + temp + " 的余数除以 3 是: "+intdivby3+" <br> "温度++如果(温度>最大值){clearInterval(theInterval);//这将停止循环}}, 1000);}

<input id="seed" type="number" placeholder="seed" value="3"><br><input id="max" type="number" placeholder="max" value="8">

<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").valuevar max = document.getElementById("max").valuevar temp = 种子var i = 1//或使用 0 立即触发第一次迭代而(温度 <= 最大值){处理迭代(温度,我);温度++我++}}函数 handleIteration(temp, i) {//temp 和 i 现在在这个函数内是安全的,我们不//需要担心 while 循环会改变它们设置超时(函数(){var intdivby2 = 温度 % 2var intdivby3 = 温度 % 3var output = document.getElementById('输出')output.innerHTML += "" + temp + " 的余数除以 2 是:" + intdivby2 + " 
"output.innerHTML += "" + temp + " 的余数除以 3 是:" + intdivby3 + "
"}, i * 1000)//<-- 改变超时时间}

<input id="seed" type="number" placeholder="seed" value="3"><br><input id="max" type="number" placeholder="max" value="8">

<button onclick="count()">Count</button><div id="output"></div>

I am 11 and just started programming. I was trying to use a while loop and I want it to display the answers in blocks instead of one huge chunk. 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. 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.

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!

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>

解决方案

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

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:

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.

But there's a catch: you need each setTimeout to use different values for 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. (You had this same problem in your code, too: that's why you were seeing '9' on the first iteration.)

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. 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.)

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>

这篇关于在 While 循环中 setTimeout 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆