简体   繁体   English

为什么这个while循环不会运行?

[英]Why will this while-loop not run?

I'm trying to learn while-loops in Javascript.我正在尝试在 Javascript 中学习 while 循环。 Why won't this while loop run even when the button is clicked and the boolean becomes true?为什么即使单击按钮并且布尔值变为真,while 循环也不会运行? Is it even possible to have while-loops react to event-driven variable changes?甚至有可能让 while 循环对事件驱动的变量变化做出反应吗?

 let run = false; let count = 0; const button = document.getElementById("startstop"); const counter = document.getElementById("counter"); button.addEventListener('click', function() { run = !run; //clever way to toggle the boolean }) while (run == true) { count++; counter.innerHTML = count; }
 <button id="startstop">Start/Stop</button> <p id="counter">0</p>

The while is running but when the page loads, so when you click on the button the while loop has already passed. while 正在运行,但在页面加载时,因此当您单击按钮时,while 循环已经通过。 You can see this in action when you place your while loop inside the click listener, however this is not the behaviour you want.当您将 while 循环放置在点击侦听器中时,您可以看到这一点,但这不是您想要的行为。 Instead use an interval to fix this issue like shown below:而是使用间隔来解决此问题,如下所示:

 let run = false; let count = 0; let interval = null; const delay = 100; const button = document.getElementById("startstop"); const counter = document.getElementById("counter"); button.addEventListener('click', function() { run = !run; if (run === true) { interval = setInterval(() => { count++; counter.innerHTML = count; }, delay) } else { clearInterval(interval) } })
 <button id="startstop">Start/Stop</button> <p id="counter">0</p>

The loop is not executed because run is false.循环未执行,因为 run 为假。

Here we can move the while to the button but that will not work because the tight loop does not give the DOM time to update.在这里,我们可以将 while 移动到按钮上,但这将不起作用,因为紧密循环不会给 DOM 时间更新。

button.addEventListener('click', function() {
  run = !run; //clever way to toggle the boolean
  while (run) {
    count++;
    counter.innerHTML = count;
  }
})

I do NOT recommend to use while loops at all to update DOM我不建议使用 while 循环来更新 DOM

This will work but the loop will run even when not updating the counter这会起作用,但即使不更新计数器,循环也会运行

 let run = false; let count = 0; const button = document.getElementById("startstop"); const counter = document.getElementById("counter"); button.addEventListener('click', function() { run = !run; //clever way to toggle the boolean }) setInterval(function() { if (!run) return count++; counter.innerHTML = count; },10)
 <button id="startstop">Start/Stop</button> <p id="counter">0</p>

A more elegant version would be to clearInterval一个更优雅的版本是 clearInterval

 let run = false; let count = 0; let tId; const button = document.getElementById("startstop"); const counter = document.getElementById("counter"); button.addEventListener('click', function() { run = !run; //clever way to toggle the boolean if (run) tId = setInterval(function() { count++; counter.innerHTML = count; }, 10) else clearInterval(tId) })
 <button id="startstop">Start/Stop</button> <p id="counter">0</p>

When you start up the page, the while loop actually ends the first time.当您启动页面时,while 循环实际上是第一次结束。 When toggling the boolean, it will not automatically rerender the dom for you.切换布尔值时,它不会自动为您重新渲染 dom。 So if you want to run the while loop, you'll need to wrap it in a function and call it.因此,如果您想运行 while 循环,您需要将它包装在一个函数中并调用它。

PS Running this code will freeze your browser btw. PS 顺便说一句,运行此代码将冻结您的浏览器。 Try adding in a delay尝试添加延迟

 let run = false; let count = 0; button.addEventListener('click', function() { run = !run; //clever way to toggle the boolean doRun(); }) const doRun = () => { while (run) { count++; counter.innerHTML = count; } } doRun()
 <button id="startstop">Start/Stop</button> <p id="counter">0</p>

The check while (run == true) { happens right after the event listener is added, at which points the value of run is still false .检查while (run == true) {在添加事件侦听器后立即发生,此时run的值仍然为false

Moreover a while loop that never stops is going to completely overwhelm the thread, making it impossible for the user to click the button.此外,永不停止的 while 循环将完全淹没线程,使用户无法单击按钮。

You could use setInterval , which runs a function every x milliseconds.您可以使用setInterval ,它每 x 毫秒运行一个函数。 That way, you can check the value of run whenever you want, without blocking the thread (which is what the while (run == true) { does).这样,您可以随时检查run的值,而不会阻塞线程(这就是while (run == true) {所做的)。

 let run = false; let count = 0; let intervalID = setInterval(tick, 1000); // 1000ms = 1sec const button = document.getElementById("startstop"); const counter = document.getElementById("counter"); button.addEventListener('click', function() { run = !run; button.textContent = run ? "Stop" : "Start"; }); function tick() { if (run) { count++; counter.innerHTML = count; } }
 <button id="startstop">Start</button> <p id="counter">0</p>

The problem with this is that you could be off by close to a whole second each time you restart the timer.这样做的问题是,每次重新启动计时器时,您可能会关闭近一秒。 To improve the time measuring you could instead use the variable count to store the actual milliseconds passed while the counter is on.为了改进时间测量,您可以改为使用变量count来存储计数器打开时经过的实际毫秒count Using another variable to store the timestamp at which the last measurement happened (or when the start button was last clicked) would also greatly improve the accuracy.使用另一个变量来存储上次测量发生的时间戳(或上次单击开始按钮的时间)也将大大提高准确性。

 let run = false; let count = 0; let previousTick = Date.now(); let intervalID = setInterval(tick, 100); // 100ms = 0.1sec const button = document.getElementById("startstop"); const counter = document.getElementById("counter"); button.addEventListener('click', function() { run = !run; button.textContent = run ? "Stop" : "Start"; previousTick = Date.now(); }); function tick() { if (run) { count += Date.now() - previousTick; counter.innerHTML = Math.floor(count / 1000); previousTick = Date.now(); } }
 <button id="startstop">Start</button> <p id="counter">0</p>

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

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