admin管理员组文章数量:1279008
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 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>
Share
Improve this question
edited Jun 11, 2017 at 16:29
Daniel Beck
21.5k5 gold badges42 silver badges60 bronze badges
asked Jun 11, 2017 at 16:24
HyperMonkeyHyperMonkey
1151 silver badge6 bronze badges
7
- I'm a little confused as to what you want it to do. Do you want it to display one line every second instead of all of it after one second? – Glen Pierce Commented Jun 11, 2017 at 16:27
- @Glen Pierce That is exactly what i want.thanks – HyperMonkey Commented Jun 11, 2017 at 16:29
- "Just started programming" in January you said you started a couple months beforehand, the fact you're young and reasonably new to programming means nothing. Just ask a succinct question and you'll get an answer and avoid downvotes. – Nick is tired Commented Jun 11, 2017 at 16:30
- 1 Sheesh, cut him a little slack. This is a pretty reasonable question, he's just misunderstood how setTimeout works. – Daniel Beck Commented Jun 11, 2017 at 16:34
-
1
Have you programmed anything asynchronous (
setTimeout
, ajax, etc) before? It doesn't cut well with loops. It would be a good motivation to learn about recursion, though. – Bergi Commented Jun 11, 2017 at 16:36
3 Answers
Reset to default 5I 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 bine 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>
Asynchronous while loop ( due to some awesome ES7 stuff (just the newest browsers support it)):
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. 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.
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...
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>
本文标签: javascriptIn a While loop setTimeout not workingStack Overflow
版权声明:本文标题:javascript - In a While loop setTimeout not working - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741295034a2370767.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论