0
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="start()">start</button>
<button onclick="stop()">stop</button>
</body>
<script>
    
    function start() {
        while(true){ 
             console.log("start")
        }
    }
    function stop() {
        console.log("stop")
    }

</script>
</html>

When I click "start" to enter the infinite loop when I click "stop", the stop will not be printed, it is blocked.

JMP
  • 4,417
  • 17
  • 30
  • 41
  • Don't introduce an infinite loop, just log "start" instead. Or do you actually want to log "start" until stop button is clicked? – Teemu Nov 05 '20 at 09:11
  • Use `setInterval` instead, or `requestAnimationFrame` if you want a non-blocking loop –  Nov 05 '20 at 09:11
  • @ChrisG JavaScript is single threaded, setInterval will also be blocked, I tried –  Nov 05 '20 at 09:24
  • Does this answer your question? [Why does a while loop block the event loop?](https://stackoverflow.com/questions/34824460/why-does-a-while-loop-block-the-event-loop) – Perrier Nov 05 '20 at 09:24
  • I know, I meant "don't use a while loop". –  Nov 05 '20 at 09:24
  • @Teemu Yes, click "start" until you click "stop" to end –  Nov 05 '20 at 09:25
  • Duplicate: [Implementing a pause and resume mechanism for javascript loop execution](https://stackoverflow.com/questions/26696717/implementing-a-pause-and-resume-mechanism-for-javascript-loop-execution) –  Nov 05 '20 at 09:26

4 Answers4

1

The problem is with how javascript is executed. Basically everything that is regarding your website is executed in one Thread (note: this isn't completely right, but it works for us), so when you have a blocking javascript script (like a while loop) it freezes your whole website.
If you now press the stop button, it won't execute, because your while-loop is still freezing the page.

The Solution:

Use setInterval instead like this:

    var interval_handle = undefined; //<- id of your interval. Used to stop it again
    function start() {
        stopMayInterval(); // Stop the loop, if already running
        interval_handle = setInterval( // Start the loop
          ()=>{ // Function that is looped
            console.log("start");
          }
        ,1); looped every 1 ms;
    }
    function stop() {
        stopMyInterval();
        console.log("stop")
    }

    /* Stops the Interval */
    function stopMyInterval(){
      if(interval_handle != undefined){
        clearInterval(interval_handle);
        interval_handle = undefined;
      }
    }

If you use it like this, javascript automatically queues your function every 1 ms after it has done every other thing it needs to execute for your site to work (like a button event). Documentation: https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

0

Browser Javascript only allows executing one script at a time by default. The simplest way around this is to use asynchronous code - for example, let's say you want to print out a message every second until the stop button is clicked:

function start() {
  if (backgroundTask) return;

  console.log("start");
  backgroundTask = setTimeout(function () { console.log("Hi!"); }, 1000);
}

function stop() {
  if (!backgroundTask) return;

  clearTimeout(backgroundTask);
  backgroundTask = null;
}
Luaan
  • 62,244
  • 7
  • 97
  • 116
0

When you use while loop, the browser will be blocked until the loop will end. It will be better to use setInterval instead.

0

If you pass a variable to a while loop it stays running in a process for as long it remains truthy. It's good if you use it on finite range values/array. Or you need to pass break; inside the while loop. You can assign setInterval to a variable where you can call clearInterval(variable) once you want to stop the process.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="start()">start</button>
<button onclick="stop()">stop</button>
</body>
<script>
    var loop
    function start() {
        loop = setInterval(() =>
          console.log("start")
        )
    }
    function stop() {
        console.log("stop")
        clearInterval(loop)
    }
</script>
</html>
syarul
  • 2,161
  • 2
  • 20
  • 22