Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is setInterval handler called while my script running?

I planned to use setInterval to simply set a variable to false, which would be inspected by the main loop to stop. Example (note: this is an example only, the acutal code is not a while() loop which would be easy to reconstruct, but a quite complex, and long to execute script generated by a closed source software actually):

var running = true;
setInterval(function () {
  if (running) {
    console.log("Stopping now!");
    running = false;
  }
}, 100);

while (running) {
  // do something ...
}

However it does not seem to work at least firefox drops a "busy script" box after a while. What's the problem with the code above? setInterval() may not be able to run if your script already runs otherwise? I couldn't find an exact specification what setInterval() does exactly.

I would need something like this, since I already have huge (and very long to execute) script, so I thought I will try to stop it after a while, then using setTimeout() to let the browser breath a bit and then continue: as the script itself does know its internal state so it can continue from any point, but it's not an option to modify the script actually ....

If it's not possible with setInterval, is there any alternative to this, without any modification in the "long to execute" code itself?

Thanks!

like image 827
LGB Avatar asked Apr 02 '26 06:04

LGB


2 Answers

If it's not possible with setInterval, is there any alternative to this, without any modification in the "long to execute" code itself?

One possibility is to make that a web worker rather than trying to use it on the UI thread. Despite people repeatedly saying so, JavaScript is not single-threaded (JavaScript, the language, is silent on the subject), not even on browsers anymore. In the browser environment, there is one main UI thread, but you can spawn other worker threads (web workers). The worker(s) and the main UI code can communicate via postMessage / onmessage.

Here's an example of a web worker in action. This page uses JavaScript on the UI thread to start a web worker, which runs on a separate thread. The worker runs for 10 seconds, busily updating a counter (this is just to simulate a long-running, calculation-intensive process), and sends updates to the UI thread every second:

Main page:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Worker Example</title>
<style type="text/css">

body {
    font-family: sans-serif;
}
</style>
<meta charset="UTF-8">
</head>
<body>

<script>
(function() {
    var worker = new Worker("worker.js");
    worker.onmessage = function(e) {
        display("Worker says " + e.data);
    };
    display("Starting worker");
    worker.postMessage("start");

    function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = String(msg);
        document.body.appendChild(p);
    }
})();
</script>
</body>
</html>

worker.js:

this.onmessage = function(e) {
    var counter, lastUpdate, now;

    if (e.data === "start") {
        // Loop without yeilding for 10 seconds, sending updates
        // to the UI every second.
        start = lastUpdate = Date.now();
        counter = 0;
        do {
            ++counter;
            now = Date.now();
            if (now - lastUpdate > 1000) {
                lastUpdate = now;
                this.postMessage(counter);
            }
        }
        while (now - start < 10000);
        this.postMessage("Done");
    }
};

(You're not required to make the worker wait for a message to start, but it's fairly common.)

like image 51
T.J. Crowder Avatar answered Apr 03 '26 19:04

T.J. Crowder


The problem is that Javascript is single-threaded. Rewrite your while loop to use setInterval itself and everything should work, since you will release the thread at the end of each loop.

like image 27
filmor Avatar answered Apr 03 '26 21:04

filmor