Introducing HTML5 Web Workers

One of the interesting and useful additions to the HTML5 standards is the support for Web Workers. Web Workers will help you design more responsive web applications then otherwise possible in the past.

What are Web Workers

Web Workers are basically a API specification that lets you create background JavaScript threads to process CPU intensive tasks. Normally in browsers a single thread is created to handle all the JavaScript code. So whatever JavaScript code is run in the browser is executed in that single thread; whether you are doing some calculation or updating page elements. The downside of this is that some CPU intensive piece of JavaScript can render the page unresponsive or slow it to a crawl.

Web Workers alleviate this problem by letting you create multiple JavaScript threads that will run independent of each other, this will prevent one CPU intensive piece of JavaScript from interfering with the UI code.

Checking Web Worker support

Before you create any Web Worker related code you will need to find if your browser supports HTML5 Web Workers. Failure to do this will send your Web Workers to slog in Never Never Land. The following code will allow you to check if your browser supports Web Workers.

/* Check if Web Workers are supported */
function getWebWorkerSupport() {
    return (typeof(Worker) !== "undefined") ? true:false;
}

Creating a simple Worker

Once we have checked that Workers are supported in the browser we are ready to put them to task. In this example we will create a simple Web Worker that will ‘Add’ or ‘Multiply’ two numbers. The example is deliberately kept simple to keep the discussion focused on Worker details; in reality you would not use Workers for such simple things, but for more elaborate and CPU intensive tasks. Below is a small piece of JavaScript code that does the actual arithmetic calculation. This our Worker. It is stored in the ‘arithmetic.js’ file.

/* arithmetic.js */
 
function addNumbers(x,y) {
    return x + y;
}
 
function mulNumbers(x,y) {
    return x*y;
}
 
/* 
   Add a event listener to the worker, this will
   be called when the worker receives a message
   from the main page.
*/
this.onmessage = function (event) {
    var data = event.data;
 
    switch(data.op) {
        case 'mult':
        postMessage(mulNumbers(data.x, data.y));
        break;
        case 'add':
        postMessage(addNumbers(data.x, data.y));
        break;
        default:
        postMessage("Wrong operation specified");
    }
};

Now that we have or Worker file ready we need to call it from our main file.
The following line will create a new Worker thread and run the code stored in ‘arithmetic.js’.

/* Create a new worker */
    arithmeticWorker = new Worker("arithmetic.js");

Once we have created Workers we need to send and receive messages from them. For that we need to add a event handler to the main calling code.

/* 
   Add a event listener to the worker, this will
   be called whenever the worker posts any message.
*/
arithmeticWorker.onmessage = function (event) {
    document.getElementById("output").value = event.data;
};

Now whenever a Worker posts a message the ‘onmessage’ event is fired and the code within it is executed. The data passed by the Worker is stored in the event.data container. We have seen how to receive a message from the Worker but how to we post one. Posting a message to the Worker is very simple.

/* Message sent by the main page to the Worker. */
arithmeticWorker.postMessage('Main says...');

The message can be a simple variable or a JSON object. The same event management applies to the Worker file. Whenever the main page posts a message to the Worker the Worker can receive the message in a ‘onmessage’ event handler, at the same time the Worker can post a message to the main page with the ‘postMessage’ method.

/* Message sent by a Worker to the main page. */
postMessage('Worker says...');

We have already seen the Worker code. Below is the code for the main file.

<!DOCTYPE html>
<body>
<input type="text" id="x" value="2" />
<br />
<input type="text" id="y" value="3" />
<br />
<input type="text" id="output" />
<br />
<input type="button" id="multButton" value="Multiply" />
<input type="button" id="addButton" value="Add" />
 
<script>
 
/* Check if Web Workers are supported */
function getWebWorkerSupport() {
    return (typeof(Worker) !== "undefined") ? true:false;
}
 
 
if(getWebWorkerSupport() == true)
{
    var x,y,message;
 
    /* Create a new worker */
    arithmeticWorker = new Worker("arithmetic.js");
 
    /* 
       Add a event listener to the worker, this will
       be called when the worker posts a message.
    */
    arithmeticWorker.onmessage = function (event) {
         document.getElementById("output").value = event.data;
    };
 
    /* Register events for buttons */
    document.getElementById("multButton").onclick = function() {
        /* Get the values to do operation on */
        x = parseFloat(document.getElementById("x").value);
        y = parseFloat(document.getElementById("y").value);
        message = {
            'op' : 'mult',
            'x'  : x,
            'y'  : y
        };
        arithmeticWorker.postMessage(message);
    }
 
    document.getElementById("addButton").onclick = function() {
        /* Get the values to do operation on */
        x = parseFloat(document.getElementById("x").value);
        y = parseFloat(document.getElementById("y").value);
        message = {
            'op' : 'add',
            'x'  : x,
            'y'  : y
        };
 
        arithmeticWorker.postMessage(message);
    }
}
</script>
</body>
</html>

Terminating Web Workers

Once the main page starts a Worker thread, the thread doesn’t terminate by itself. The calling page has to explicitly ask the Worker to terminate. This may become necessary because creating each new Worker consumes precious browser resources, which you will need to reclaim once the Workers task is no longer required.

/* Terminate the Worker */
arithmeticWorker.terminate();

Workers and DOM accessibility

Due to the threading nature of Workers they do not have access to the following JavaScript objects.

* The DOM (it’s not thread-safe)
* The window object
* The document object
* The parent object

VIEW DEMO

5 thoughts on “Introducing HTML5 Web Workers

Comments are closed.