setInterval continues to run after clearInterval is called - javascript

I'm working on a countdown timer for a quiz app I'm building as a homework assignment during bootcamp. Right now everything is functioning properly when rendered except that once the setInterval function inside of startQuiz() hits 0 it's supposed to clear the interval. However, the innerHTML written to the document keeps flashing momentarily as if the countdown is still running. I think it's probably a return in the wrong place but I've tried adding, subtracting, and moving returns throughout the script and am not seeing where the solution is.
var startButton = document.querySelector("#startButton");
var time = document.querySelector("#time");
var countdown = document.querySelector("#countdown");
var timeLeft;
var userScore;
startButton.addEventListener("click", startTimer);
function startTimer() {
var startCount = 5;
setInterval(function(){
if(startCount <= 0) {
clearInterval(startCount=0);
startQuiz();
}
countdown.innerHTML = startCount;
startCount -=1;
}, 1000);
return;
}
function startQuiz() {
timeLeft = 10;
quizQuestions();
setInterval(function(){
if(timeLeft <= 0) {
clearInterval(timeLeft=0);
gameOver();
}
time.innerHTML = timeLeft;
timeLeft -=1;
}, 1000)
return;
}
function gameOver() {
document.getElementById("quizQuestion").innerHTML = "GAME OVER";
return;
}
function quizQuestions() {
document.getElementById("quizQuestion").innerHTML = questionA.question;
return;
}
This is the entire script so far. I only left out the var definition for questionA since it is an object with multiple key value pairs and is not relevant to the issue so I omitted it to save space. The startTimer() function works properly as a separate countdown timer to start the game but I included it in the code in case it's interfering with the startQuiz() function in some way.

setInterval returns integer for interval identification. You must use this integer to clear interval.
var intervalId = setInterval(function(){
if(timeLeft <= 0) {
clearInterval(intervalId);
gameOver();
}
time.innerHTML = timeLeft;
timeLeft -=1;
}, 1000);

// assign to a variable...
const interval = setInterval(callback, timing)
// ...then pass that variable to clearInterval
clearInterval(interval)
In this example, interval will be a number (incremented each time a call to setInterval or setTimeout is made). If you pass someOtherVariable = 0 to clearInterval, you're actually passing 0, because assignment returns the value assigned. The incrementing interval/timeout value starts from 1, so the interval identified by 0 will never exist, thus clearing it is a no-op.

Related

How to stop timer and check for value if value is not met continue and else stop timer and do something

So like the title says i have this timer and i would like that once that it reaches 0, it should check if a variable called "user_energy" in this case is equal to 100. If it is than the timer will stop, and it could do something. Like for example just a console.log("It works") and if its not then it should repeat itselfs.
How would you be able to do something like that?
This is the code:
function startTimer() {
var interval = 10000;
{
localStorage.endTime = +new Date + interval;
}
if(!localStorage.endTime)
{
startTimer();
}
setInterval(function()
{
var remaining = localStorage.endTime - new Date;
if( remaining >= 0 )
{
$('#energytimer').text( Math.floor( remaining / 1000 ) );
} else
{
startTimer();
}
}, 100);
}
It's a little unclear how the localStorage stuff fits into the question, but here's a simple countdown timer that does what you are asking. You can adapt this to store the counter in localStorage if that's what you want to do.
The key is to assign a variable to the return value from the timer so that you can call clearTimeout() and pass that variable and stop the timer later.
let timer = null; // <-- This will hold a reference to the timer
var counter = 5;
timer = setInterval(function(){
if(counter === 0){
clearTimeout(timer); // Stop the timer
console.log("Times up!");
} else {
$("#energytimer").text(counter--);
}
}, 1000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="energytimer"></div>

How do I loop this function?

I am using Odometer to show an animated counter:
setTimeout(function (){
$('.odometer').html(8567);
}, 1000);
</script>
<script>
window.odometerOptions = {
duration: 3000
};
I would like the counter to start over at the value I've defined in my html (which is 1000) and then count back up to 8567 and repeat indefinitely. I've tried:
$(document).ready(function () {
function loop(){
setTimeout(function (){
$('.odometer').html(8567);},1000,loop);
loop();
});
But it breaks the counter. I'm assuming I can't mix the setTimeout while defining the loop, but don't know what else to try. The 1000 in the setTimeout function is just a coincidence and is the delay to start the function after page load.
If you want to repeatedly call a function over time like this you should use setInterval not setTimeout.
You need to keep track of the current value of the loop, yours right now is setting the counter to 8567 every time.
const start = 1000;
const max = 1010;
var c = start;
var el = document.getElementById('counter');
function counter() {
if (c > max) {
c = start;
}
el.innerHTML = c + "";
c++;
}
counter(); // Optional, can exclude if you want to delay starting the timer
setInterval(counter , 1000)
<div id="counter"></div>

For loop with a timeout doesn't seem to work and gives weird numbers

I want to make a countdown in javascript, with simple variables, for loop, set timeout.
I get stuck when trying to make a for loop update realtime (every second) right now I get -1 in webpage.
//HTML PART
<p id=timer>0</p>
//JS PART
var timer = 10;
var text = "";
function f() {
for (timer; timer > 0; timer--) {
text += timer + "<br>";
}
timer--;
if( timer > 0 ){
setTimeout( f, 1000 );
}
}
f();
document.getElementById("timer").innerHTML = timer;
Please explain the error and if I'm doing any stupid mistakes
Looks like you want to show timer value from 10 to 0 by changing the value every second. If so, you can do like this:
1. You need to correct your html by putting quotes around timer like this <p id="timer">0</p>
2. You need to remove for loop as I have commented.
3. Move document.getElementById("timer").innerHTML = timer; inside function f().
var timer = 10;
//var text = "";
function f() {
//for (timer; timer > 0; timer--) {
// text += timer + "<br>";
//}
document.getElementById("timer").innerHTML = timer;
timer--;
if (timer >=0) {
setTimeout(f, 1000);
}
}
f();
<p id="timer">0</p>
You can do it like so, I provided comments in code for explanation:
var count = 10;
function timer(targetValue) {
// display first number on screen
document.getElementById("timer").textContent = count;
// decrease count by 1
count--;
// check if timer is still grater than target value
if (count >= targetValue) {
// call timer() function every second to update
setTimeout(timer, 1000, targetValue);
}
}
timer(0);
Counts down from 10 to 0.
Want to count down from 10 to 5? Simply use timer(5)

SetTimeout. Stop timer

As in this example to stop setTimout?
var i = 1;
var timerId = setTimeout(function tick() {
if (i == 5) clearTimeout(timerId);
i++;
console.log("Tick");
timerId = setTimeout(tick, 2000);
}, 2000);
I know this code you can change and then everything will work, but I wanted to understand why the first example does not work.
var i = 1;
var timerId = setTimeout(function tick() {
console.log('Tick');
if (i < 5) setTimeout(tick, 2000);
i++;
}, 2000);
The first code snippet continues looping because:
You are changing the timerId with every new timeout you set.
You are clearing the timeout that has already finished executing (because it has called the function), and then creating a new one.
You should be using setInterval() instead of setTimeout(), as an interval will keep repeating indefinitely at the specified frequency, whereas a timeout will only execute once after the specified time has elapsed.
The first example isn't working because you're always setting a timeout, no matter the value of i. Add a return statement if i is equal to 5
var i = 1;
var timerId = setTimeout(function tick() {
if (i == 5) {
return;
}
i++;
console.log("Tick");
timerId = setTimeout(tick, 2000);
}, 2000);
It's OK to clearTimeout after the timer expired, but it's not necessary.
and just because of that, your second code snippet is superior to the first one.
and in your first code snippet, you always set the timeout, even if your if condition is met, and you are suppose to return,
i will re-write the function as shown below
var i = 1;
function tick() {
if (i == 5) {
return;
}
i++;
console.log("Tick");
setTimeout(tick, 2000);
}
setTimeout(tick, 2000);
or using interval as
var i = 1;
function tick() {
if (i == 5) {
clearInterval(timerId);
return;
}
i++;
console.log("Tick");
}
var timerId = setInterval(tick, 2000);

setting a one minute timer in JavaScript memory aid game

<div id="counter">1:00</div>
function countdown() {
var secs = 60;
function tick() {
var counter = document.getElementById("counter");
secs--;
counter.innerHTML = "0:" + (secs < 10 ? "0" : "") + String(secs);
if( secs > 0 ) {
setTimeout(tick, 1000);
} else {
alert("Game Over");
}
}
tick();
}
countdown(60);
I am having a problem with this portion of my game. I'm trying to set a 60 seconds timer for the game that starts at 60 and ends at 0, when it gets to 0 the game stops and an alert shows that the game is over.
I am very new to programming, so please give me as many feedbacks as you can. I found this code on the internet, and I figured out most of it, could you also tell me what does the tick() function do over here?
Here is one way you can do it:
First declare a variable you will use for an interval (should be 'global', attached to window):
var countDownInterval = null;
Then, a function to trigger the tick interval, you should call this whenever the game is ready to start:
function startCountDown()
{
countDownInterval = setInterval(tick,1000); //sets an interval with a pointer to the tick function, called every 1000ms
}
which will call the tick function every second:
function tick()
{
// Check to see if the counter has been initialized
if ( typeof countDownInterval.counter == 'undefined' )
{
// It has not... perform the initialization
countDownInterval.counter = 0; //or 60 and countdown to 0
}
else
{
countDownInterval.counter++; //or --
}
console.log(countDownInterval.counter); //You can always check out your count # the log console.
//Update your html/css/images/anything you need to do, e.g. show the count.
if(60<= countDownInterval.counter) //if limit has been reached
{
stopGame(); //function which will clear the interval and do whatever else you need to do.
}
}
and then the function where you can do everything you need to do after game has finished:
function stopGame()
{
clearInterval(countDownInterval);//Stops the interval
//Then do anything else you want to do, call game over functions, etc.
}
You can fire up the counter at any time by calling startCountDown();
Pseudo code of tick:
function tick() {
reduce counter variable;
if counter > 0
wait for 1 second; (This is what setTimeout(tick, 1000) means)
call tick() again (recursively)
}
else {
game over
}
}
Something like this?
var countdown = function(sec, tick, done) {
var interval = setInterval(function(){
if(sec <= 0) {
clearInterval(interval);
done();
} else {
tick(sec)
sec--;
}
}, 1000)
}
countdown(10, console.log, function(){console.log('done')})

Categories