How HTML5 Web Workers make unicorns run

A unicornOne of the things that HTML5 brings us is Web Workers. These things are great for enhancing user experience in webapplications or javascripts that contain heavy computations or other sort of long running scripts.

Web Workers are like threads, which you might know from other development platforms. The definition of threading is the following according to Wikipedia:

“The threaded programming model provides developers with a useful abstraction of concurrent execution.”

Let’s start with identifying the problem.
For the working example for this post, check out this page and hit the ‘Freeze’ button. Under this freeze button there is a function that does a huge secret calculation that is supposed to use a lot of your CPU’s time. Actually it’s not that secret, see code sample 1 for the code. Notice that the unicorn stops moving for a while when you press that button. The freeze function is freezing the UI while executing. (Thank you Captain Obvious). See diagram 1.

// Code sample 1 - Secret freeze function
function freeze() {
    var total = 0;
    for (var i = 0; i < 100000; i++)
        for (var k = 0; k < 20000; k++) total++;
    return total;
}

Diagram 1 - Single threaded script execution

Obviously, this causes the user to wait, and that’s bad practice. Nobody likes to wait.
Web Workers enable you to start another thread that can process computations parallel to the browser’s so-called UI thread. (That executes your “normal” javascript)
With the result of not blocking the user interface.
Simply put; you delegate your heavy computations to another process, which, when ready, will send the result back to your UI thread. This is visualized in diagram 2.

Diagram 2 - Multi threaded script execution

Delegating the long running function to another thread leaves computing space in the UI thread open for other computations. UI computations of course, as it is the UI thread.
Doing this is actually quite simple, and requires to put your code in a new javascript file that will  execute in the worker’s context. Running a script in the worker context means that the script does not have access to the DOM or anything else that is not thread-safe.

Exchanging data between the UI and Worker is being done by the Worker.postMessage method. This method requires one parameter, the data you want to send.
This data is internally serialized as JSON by most browsers to prevent callbacks or other pointers being passed (which would potentially cause cross thread errors). (source)
Code example 2 demonstrates how to create a worker in javascript, and code example 3 demonstrates how the worker script itself should be defined. Notice that event handlers/callbacks are used to start and communicate between the Worker and the UI thread.

// Code example 2 - Creating the Worker and listen to onmessage
var worker = new Worker('webworker.js');
worker.addEventListener('message', function (event) {
    document.getElementById('calculation').textContent = event.data;
}, false);
// Code example 3 - webworker.js
self.addEventListener('message', function(event) {
    var total = 0;
    for (var i = 0; i < 100000; i++) {
        for (var k = 0; k < 30000; k++) {
            total++;
        }
    }
    self.postMessage(total);
}, false);

Inside webworker.js, the self keyword is used to approach the Worker’s API. In here you also see that we add a listener to the onmessage event, and use the Worker.postMessage method to send the output back to the UI thread.
You can start the worker from the UI thread (your normal HTML page or javascript) by using the Worker.postMessage method, as seen in code example 4.

// Code example 4 - Starting the worker
var worker = new Worker('webworker.js');
worker.addEventListener('message', function (event) {
    document.getElementById('calculation').textContent = event.data;
}, false);

worker.postMessage(null); // postMessage parameter accepts everything that’s serializable.

Obviously, you don’t want to stop a unicorn from running across your screen. So if you delegate the freeze function to a Web Worker, you get the result as in diagram 3.

Diagram 3 - Delegate the big calculation to another thread/worker, so the unicorn can keep running

Now click the “Via worker” button in the working example page.
Yay awesome, the unicorn can continue to run across your screen in the meantime! So yes, that’s what Web Workers are good for, making unicorns run across your screen.

No but seriously, i couldn’t think of a more interesting use-case.. But you can fill in your own use-case for a long running function that causes the UI thread to block.

Of course, you want to know in which browsers Web Workers are supported. Fortunately, on desktop browsers the Web Workers are widely supported (although, IE10+). A bit less fortunate is the support on mobile browsers, with the exception of Opera Mobile 11 no mobile browser supports Web Workers. For a comprehensive overview of supported browsers, take a look at the MDN page “Using web workers”.

A more in-depth explanation of HTML5 Web Workers can be found at the HTML5 Rocks website.