Reputation: 63
I am having trouble looping between 2 colours of the body forever. It only loops once.
I am using the 'enter' key to trigger the loop and the 'space' key to stop the loop.
const red= () => {
document.body.style.backgroundColor = "red";
}
const blue= () => {
document.body.style.backgroundColor = "blue";
}
const both = () => {
setTimeout(() => red(), 1000);
setTimeout(() => blue(), 2000);
}
document.body.addEventListener("keydown", function() {
if (event.keyCode == 13) {
setInterval(both(), 3000);
}
if (event.keyCode == 32) {
clearInterval(both());
}
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Looping Colors</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<script src="script.js"></script>
</body>
</html>
Upvotes: 2
Views: 273
Reputation: 12796
The error you make in your code currently, is that you:
red
and blue
and assign the value as the callback for the timeout (which is undefined)both
isn't returning the reference to the timeoutssetTimeout
runs exactly onceclearInterval
doesn't work on a function reference as you believe it is, but with the result of setInterval
setTimeout
might be less appropriate, you could use setInterval
easierIn the below code, I added an extra toggle
method, that just uses an function property count
to toggle between red
and blue
, both
returns the value of setInterval
and assigns it to a function property interval
to keep track of that interval, and then clears that one
const red= () => {
document.body.style.backgroundColor = "red";
}
const blue= () => {
document.body.style.backgroundColor = "blue";
}
const toggle = () => {
// when toggle.count doesn't exist, use 0 and increase with 1
toggle.count = (toggle.count || 0) + 1;
// when even -> call red() otherwise call blue()
// you could also verify here what is the backgroundColor
toggle.count % 2 === 0 ? red() : blue();
}
// returns the result of `setInterval` so the interval can be cleared
const both = () => setInterval( toggle, 1000 );
document.body.addEventListener("keydown", function keyhandler() {
if (event.keyCode == 13 && !keyhandler.interval) {
// keep the result of both (setInterval) as reference to the interval
// mind you, pressing enter twice would leave 1 interval running indefinitely
// unless you check if interval has a value
keyhandler.interval = both();
}
if (event.keyCode == 32) {
clearInterval( keyhandler.interval );
// delete the interval property so you can restart the loop afterwards
delete keyhandler.interval;
}
});
Upvotes: 2
Reputation: 393
Your first problem is setTimeout
and setInterval
take an input of a function not the result of a function. Instead of setTimeout(red(), 1000)
you would write setTimeout(red, 1000)
Your second problem is clearInterval
doesn't take a function. Instead it takes the return value of the setInterval
function:
var int = setInterval(both, 3000);
clearInterval(int);
Full updated code:
const red= () => {
document.body.style.backgroundColor = "red";
}
const blue= () => {
document.body.style.backgroundColor = "blue";
}
const both = () => {
setTimeout(red, 1000);
setTimeout(blue, 2000);
}
document.body.addEventListener("keydown", () => {
let bothInt;
if (event.keyCode == 13) {
bothInt = setInterval(both, 3000);
bothIntClear = false;
}
else if (event.keyCode == 32) {
clearInterval(bothInt);
}
});
Keep in mind it might take a while for the colors to stop switching because the functions are still in the event queue.
Upvotes: 1