HTML5 Zone is brought to you in partnership with:

Senior Software Developer with aim for Architect. I code, teach, write blog posts, garden, raise chickens, and am married with 2 beautiful and smart girls. Gerard is a DZone MVB and is not an employee of DZone and has posted 13 posts at DZone. View Full User Profile

An Introduction to HTML 5 Web Workers

02.10.2012
| 6922 views |
  • submit to reddit
Prior to HTML 5 Web Workers, all JavaScript code would run in the same thread as the UI of that browser window. The result was that all long-running scripts would cause the browser window to freeze until processing finished. If the script took long enough, the browser would prompt the user to see if he/she wanted to stop the unresponsive script.

Web workers allow for script to run in a separate thread from the browser window's UI. This allows long-running scripts to take place without interfering with the browser's user interface (the window stays responsive to input, like clicks and scrolling, even while processing).

As a result of running in a separate thread from the browser's UI the worker thread does not have direct access to the DOM or other UI objects.

If the worker thread needs the UI updated based on processing, the JavaScript that created the worker thread can set up a callback function to listen for messages from the worker. The main UI thread could then respond to the messages from the worker and do the proper UI modification.

One thing to be aware of with web workers is that they are not intended to be used in large numbers and are expected to be long-lived. The worker threads also have a high start-up performance cost as well as a high memory cost per worker instance.


Types of Web Workers

There are two types of web workers available: Dedicated Workers and Shared Workers.

Dedicated workers are linked to their creator. They are also a bit simpler to create and work with than shared workers.

Shared workers allow any script from the same origin/domain to obtain a reference to the worker and communicate with it.


Browser Support

Dedicated Web Workers are supported in Firefox 3.5+, Chrome 5+, and Safari 5+ (I've read that dedicated web workers are supported in Chrome 4 and Safari 4 as well but I haven't tested those browsers to know for sure).

Shared Web Workers are supported in Chrome 5.0+ and Safari 5.0+. I haven't tested Shared Web Worker support in Chrome 4 or Safari 4 so I don't know if those browsers support it or not.

Firefox does not appear to support Shared Web Workers (tested in 3.6.8 as well as 4.0 beta 2).

Internet Explorer does not yet support either type of web worker (tested in IE 8 as well as IE 9 Preview 3).


Test for Browser Features

Because web workers are a relatively new technology, not all browsers will support them. Even in a browser that supports one type of web worker, it might not support the other type (Firefox, for example, currently only supports dedicated web workers).

It is always best to test if a browser supports a particular feature before trying to use it.

The following is an example of how you would test if a browser supports Dedicated Web Workers or Shared Web Workers:
    // Test if Dedicated Web Workers are available
    if(window.Worker) { g_bDedicatedWorkersEnabled = true; }
    // Test if Shared Web Workers are available
    if(window.SharedWorker) { g_bSharedWorkersEnabled = true; }

Dedicated Web Workers

To create a dedicated web worker, you simply create a new instance of the Worker object passing in a string that specifies the location of the JavaScript file for the worker code. The following is an example of creating a dedicated worker instance:
var aWorker = new Worker("DedicatedWebWorker.js");
The worker object was designed to accept a string (location of the JavaScript file) rather than a function in order to prevent a developer from creating a closure that would allow the worker thread to gain direct access to the browser's DOM or other page elements.

Communication between the creator of the worker thread and the worker thread itself is achieved by means of postMessage calls. To pass a message to the worker thread you would do the following:
    aWorker.postMessage("Hello from the main page");
In order for the creator of the worker thread to receive messages from the worker thread, you will need to set up a function to receive the 'onmessage' event. The following is an example of how you would attach a function to the onmessage event:

    aWorker.onmessage = OnWorkerMessage;
    function OnWorkerMessage(evt)
    {
    alert("Worker's message: " + evt.data);
    }
Within the JavaScript file of the worker thread (DedicatedWebWorker.js in our case) you would attach a function to the 'onmessage' event to receive messages from the thread that created the worker.

The following is an example of a worker thread attached to the onmessage event:

    onmessage = OnCreatorMessage;
    function OnCreatorMessage(evt)
    {
    var sReturnMessage = ("Hello from the worker thread! This is what you sent my way: " + evt.data);
    // Pass our message back to the creator's thread
    postMessage(sReturnMessage);
    }

Shared Web Workers

Shared web workers provide a way for any window, from the same origin/domain (SomeWebSite.com for example), to share the use of a worker thread.

Since worker threads take time to start initially and use a lot of memory per worker, being able to share the worker rather than creating one for each open window can improve performance. The trade off, however, is that the shared worker objects are a bit more involved to set up than dedicated workers are.

To create a shared web worker, you create an instance of the SharedWorker object and pass in a string indicating the location of the JavaScript file for the worker thread. The following is an example of creating a SharedWorker instance:

var aSharedWorker = new SharedWorker("SharedWorker.js");
To receive messages from the shared worker thread you attach to the 'onmessage' event but in a slightly different way compared to that of a dedicated web worker. In this case, you need to access the 'port' object of the shared worker instance and then attach to the port object's onmessage event as in the following example:

aSharedWorker.port.onmessage = OnWorkerMessage;
Rather than using the above method to attach to the onmessage event, you can also use the addEventListener function as in the following example:

    // uses 'message' (not 'onmessage' as in previous
    // examples)
    aSharedWorker.port.addEventListener("message", OnWorkerMessage, false);
    // Required when using addEventListener
    aSharedWorker.port.start();
The OnWorkerMessage function itself is shown below (no difference compared to how it worked with dedicated web workers):

    function OnWorkerMessage(evt)
    {
    alert("Worker's message: " + evt.data);
    }
For each additional window that wants to connect with the shared worker, you simply repeat the above steps in each window.


Communication with the shared worker thread is achieved by means of postMessage calls on the port object. To pass a message to the shared worker thread you would do the following:

aSharedWorker.port.postMessage("Hello from Page 1");
Within the JavaScript file of the shared worker thread (in our case SharedWorker.js) you first attach to the 'onconnect' event which is called whenever a new object obtains a reference to the shared worker thread.

When the onconnect event fires you then attach to the onmessage event of the port passed in so that you can send/receive messages with the newly connected object.

    // event triggered whenever an object attaches to this
    // shared worker
    onconnect = function(evt)
    {
    // Get the port of the newly attached object.
    // Attach to the onmessage event so that we
    // can send/receive messages with the newly
    // attached object
    var port = evt.ports[0];
    port.onmessage = function(e){ OnCallerMessage(e, port); }
    }

    function OnCallerMessage(evt, port)
    {
    var sReturnMessage = ("Hello from the SharedWorker thread! This is what you sent my way: " + evt.data);

    port.postMessage(sReturnMessage);
    }
In Closing

I hope you found this post useful in understanding the basics of HTML 5 Web Workers.

For more detailed information the the HTML 5 Web Workers specification you can view it by clicking on the following link: http://dev.w3.org/html5/workers/


Update: If you are interested, I have now posted a follow-up to this article called 'A Deeper Look at HTML 5 Web Workers' which examines things like multiple shared workers, importing JavaScript files, and using the XMLHttpRequest object from within a worker thread.

Source: http://cggallant.blogspot.com/2010/08/introduction-to-html-5-web-workers.html

Published at DZone with permission of Gerard Gallant, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)