There are various things that can cause a script to start executing. Reading a <script> tag is one such thing. An event firing is another.
Even though events can fire at any time, no two scripts in a single document ever run at the same moment. If a script is already running, event handlers and script execution is blocked until previous actions are completed their execution. This is the reason why a document will freeze when a script runs for a long time.
The browser cannot react to clicks and other events inside the document because it can't run event handlers until the current script finishes running.
For cases where you really do want to do some timeconsuming thing in the background without freezing the page, browsers provide something called web workers. A worker is an isolated JavaScript environment that runs alongside the main program for a document and can communicate with it only by sending and receiving messages.
Assume we have the following code in a file called code/squareworker.js:
addEventListener("message", function(event) { postMessage(event.data * event.data); });
Imagine that squaring a number is a heavy, long-running computation that we want to perform in a background thread. This code spawns a worker, sends it a few messages, and outputs the responses.
var squareWorker = newWorker("code/squareworker.js"); squareWorker.addEventListener("message", function(event) { console.log("Theworkerresponded:", event.data); }); squareWorker.postMessage(10); squareWorker.postMessage(24);
The postMessage function sends a message, which will cause a "message" event to fire in the receiver. The script that created the worker sends and receives messages through the Worker object, whereas the worker talks to the script that created it by sending and listening directly on its global scope which is a new global scope, not shared with the original script.