1

I'm trying to make a simple countup timer with a start/stop button. I don't understand why the while loop crashes the page even though it has a 1sec delay. Is there a easier way to keep updating the time until I press the button?

let startButton = document.getElementById("btn-start-stop");
let timerOutput = document.getElementById("timer");
let runTimer = false;
let sec = 0;
let startTimer = false;
console.log(startTimer);
startButton.onclick = function () {
  startTimer = !startTimer;
  while (startTimer) {
    setInterval(function () {
      console.log(sec);
    }, 1000);
  }
};
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="an exercise to manipulate DOM-elements">
    <meta name="author" content="lars berg">
    <meta name="keywords" content="a template for at exercise">
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <title>DOM | Manipulate</title>
    <script src="https://kit.fontawesome.com/fa41e523cd.js" crossorigin="anonymous"></script>
    <script src="scripts/script.js" defer></script>
</head>

<body>
    <header>
        <h1>DOM | Manipulation</h1>
    </header>
    <main>
        <div class="flex-container">
            <div class="counter-container">
                <h2 class="h2-counter">How long time will it take to read this information?</h2>
                <div id="timer">
                    00:00:00
                </div>
                <div class="buttons">
                    <button id="btn-start-stop" type="button">
                        <i class="fa-solid fa-play fa-2x"></i>
                    </button>
                    <button id="btn-reset" type="button">
                        <i class="fa-solid fa-arrow-rotate-left fa-2x"></i>
                    </button>
                </div>
            </div>
        </div>
    </main>
    <footer>
    </footer>
</body>

</html>
gogosimba
  • 65
  • 7

3 Answers3

3

You should not use a while() loop as this will block the thread.

Use setInterval() to preform an action at a specific interval (1000ms), and use clearInterval() to stop it on second press

Regarding the seconds to HMS, I'ved used this SO one-liner and made a function of it that will be called after we've bumped the seconds.

let startButton = document.getElementById("btn-start-stop");
let timerOutput = document.getElementById("timer");

let sec = 0;
let timer = null;

startButton.onclick = function () {
    if (timer) {
        clearInterval(timer);
        timer = null;
    } else {
        timer = setInterval(() => ++sec && update(), 1000);
    }
};

function update() {
    timerOutput.innerHTML = new Date(sec * 1000).toISOString().substr(11, 8);
}
<script src="https://kit.fontawesome.com/fa41e523cd.js" crossorigin="anonymous"></script>

<header>
    <h1>DOM | Manipulation</h1>
</header>
<main>
    <div class="flex-container">
        <div class="counter-container">
            <h2 class="h2-counter">How long time will it take to read this information?</h2>
            <div id="timer">
                00:00:00
            </div>
            <div class="buttons">
                <button id="btn-start-stop" type="button">
                    <i class="fa-solid fa-play fa-2x"></i>
                </button>
                <button id="btn-reset" type="button">
                    <i class="fa-solid fa-arrow-rotate-left fa-2x"></i>
                </button>
            </div>
        </div>
    </div>
</main>
0stone0
  • 34,288
  • 4
  • 39
  • 64
  • _"at a specific interval"_ - _"specific"_ as in "Please execute this task _as soon as possible after_ milliseconds" – Andreas Oct 19 '22 at 12:52
  • It works but I don't understand why. How come the update function runs continuously? I guess I have a bad understanding on how javascript works. I thought the code was loaded in once. You press the button and update runs if timer is true. How come it keeps running more than once without a loop? – gogosimba Oct 19 '22 at 13:02
  • Read the docs on [`setInterval`](https://developer.mozilla.org/en-US/docs/Web/API/setInterval): "**..repeatedly calls a function or executes a code snippet, with a fixed time delay between each call.**" – 0stone0 Oct 19 '22 at 13:06
0

While loop will block your thread because JavaScript is single threaded language.

let startButton = document.getElementById("btn-start-stop");
let timerOutput = document.getElementById("timer");
let runTimer = false;
let sec = 0;
let startTimer = false;
console.log(startTimer);
startButton.onclick = function () {
  
 // you can change your button here 
    setInterval(function () {
      console.log(sec);
      sec = sec+1
     // implement your logic here for seconds
     
    }, 1000);
  
};
0

Because while looping, you are generating a call stack of setTimeout again and again which seems to crash the browser stack check below sample code while no loop just use recursive approach

let startButton = document.getElementById("btn-start-stop");
let timerOutput = document.getElementById("timer");
let runTimer = false;
let sec = 0;
let startTimer = false;
let clearTime
let count = 0
startButton.onclick = function () {
 clearTime =  setTimeout("startWatch( )", 1000)
};
function startWatch(){
 setInterval(function () {
      console.log(count);
       count++
    }, 1000);
}
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="description" content="an exercise to manipulate DOM-elements">
    <meta name="author" content="lars berg">
    <meta name="keywords" content="a template for at exercise">
    <link rel="stylesheet" type="text/css" href="css/style.css">
    <title>DOM | Manipulate</title>
    <script src="https://kit.fontawesome.com/fa41e523cd.js" crossorigin="anonymous"></script>
    <script src="scripts/script.js" defer></script>
</head>

<body>
    <header>
        <h1>DOM | Manipulation</h1>
    </header>
    <main>
        <div class="flex-container">
            <div class="counter-container">
                <h2 class="h2-counter">How long time will it take to read this information?</h2>
                <div id="timer">
                    00:00:00
                </div>
                <div class="buttons">
                    <button id="btn-start-stop" type="button">
                        <i class="fa-solid fa-play fa-2x"></i>
                    </button>
                    <button id="btn-reset" type="button">
                        <i class="fa-solid fa-arrow-rotate-left fa-2x"></i>
                    </button>
                </div>
            </div>
        </div>
    </main>
    <footer>
    </footer>
</body>

</html>