I'm writing a short program to learn about Promises in JavaScript.
The goal of the program is to print a list of numbers (decreasing from 5 to 0) onto a HTML page, with a delay of 0.5s between each number. After the 0 is printed, a confirm box pops up and allows the user to print the same numbers again or stop.
Currently, the code below is mostly working but it acts very strangely during the first and second iteration of the inner loop (in the countdown()
function) - between printing the first 5
and 4
.
I've debugged it a lot in chrome dev to try to figure out what's happening, so I've included a step-by-step guide as to what the program is actually doing (or appears to be doing) beneath the code section, with the strange behaviours in bold.
This is an unmarked assignment for university and I managed to stump my professor so any help is much appreciated. Thanks in advance!!
// wait time for setTimeout
var wait = 500;
function timer(ms) {
return new Promise((res) => {
setTimeout(res, ms);
});
}
async function countdown() {
for (let i = 5; i >= 0; i--) {
document.write("<br>");
document.write(i);
console.log(i);
await timer(wait).then();
}
var c = confirm("Do you want to go again?");
document.write("<br>User Confirm:");
document.write(c);
console.log(c);
return c;
}
async function repeatRun() {
var prom = new Promise(async(res, rej) => {
r = await countdown();
if (r) {
res();
} else {
rej();
}
});
prom.then(
data => {
document.write("<br>RERUN");
console.log("RERUN");
repeatRun();
},
error => {
document.write("<br>ENDED");
console.log("ENDED");
}
);
}
repeatRun();
<!DOCTYPE html>
<html>
<head>
<title>Countdown</title>
</head>
<body>
<h1>Countdown</h1>
<p>Internet Applications Ex1.</p>
</body>
</html>
This is what my program is doing step by step:
displays HTML page title etc
enters
script
tagenters
repeatRun()
creates Promise variable
prom
and enterscountdown()
first iteration of
for
loop (iei=5
)5.1. prints
<br>
and5
usingdocument.write()
, both are appended to the HTML body5.2. enters
timer()
5.3. returns
new Promise
5.4. this promise returns to
prom.then()
insiderepeatRun()
instead of toawait timer()
call like i expectedI have tried this with and without
.then()
afterwards and it does the same thing [this happens in one step on the Chrome debugger]exits the
script
tagre-enters the
script
tag, but not from the beginning: it returns to thefor
loop and decreasesi
current HTML file:
<html> <head> <title>Countdown</title> </head> <body> <h1>Countdown</h1> <p>Internet Applications Ex1.</p> <script>...</scri pt> <br> "5" </body> </html>
the next document.write() call, instead of appending
<br>
to the HTML body, replaces the old HTML body with<br>
, thehead
tag is also erasedthe next document.write() appends
i
(now 4) to the new HTML file current HTML file:<html> <head></head> <body> <br> "4" </body>
this is where the program starts to behave as expected 10. enters the
timer()
function and then returns tocountdown()
afterwards 11. loops as expected untili=0
11.1. `document.write()` appends to HTML body instead of rewriting
11.2. `timer()` function is called and returns to `countdown()` function afterwards
- after this loop, the confirm window pops up : I click "ok" and
true
is stored inc
, printed usingdocument.write()
, and returned and stored inr
- since
r=true
,if
succeeds andres()
is called - enters the
prom.then()
and thendata =>
anddocument.write
appends"<br>RERUN"
to HTML body correctly - the
repeatRun()
function is called recursively - creates new promise var and calls
countdown()
- this time, the
for
loop happens as expected (ie in step 11) fromi=5
toi=0
- after the loop, I click "cancel" in the confirm window,
c
is set tofalse
, printed, and returned and stored inr
- since
r=false
,if
fails andrej()
is called - enters the
prom.then()
and thenerror =>
and document.write appends"<br>ENDED"
to HTML body correctly - exits
script
tag