Introducing Web Workers

The HTML 5 specification introduces a new technology called Web Workers, allowing developers to spawn new threads for processing JavaScript code. This is a major improvement from the current state of the web, as it allows JavaScript code to execute outside of the UI thread, so your application is still responsive during long-running scripts. However, due to the nature of Web Workers there are restrictions to what they can and cant do, and how to interact with them. Todays article will explain what they are and how to use Web Workers.

How to do it…

To start a Web Worker, you point it at a JavaScript file:

var myWorker = new Worker("myworker.js");

Once you have a worker, you can subscribe to message events from the worker:

myWorker.onmessage = function(event) {
	console.log("Web Worker returned: " + event.data);
};

Additionally, you can subscribe to error events from the worker:

myWorker.onerror = function(event) {
	console.log("There was an error in " + event.filename + " at " + event.lineno + ": " + event.message");
};

A message can be passing into the Web Worker using:

myWorker.postMessage({foo: bar});
// then inside the Web Workers code
onmessage = function(event) {
	postMessage(event.data.foo + " == bar");
};

The scripts executed by the Web Worker ("myworker.js" in this example) have a global function that allows them to import other scripts:

	importScripts("foo.js", "bar.js", …);

And a Web Worker can be stopped by calling:

myWorker.terminate();

How it works…

Instantiating a new Web Worker creates a new processing thread that executes the desired script. The thread executes until it is finished or the terminate() function is called. The code executed by the Web Worker is normal JavaScript, but does not have access to the DOM, since making the DOM threadsafe would break the web. If you need to manipulate the DOM, your Web Worker should send messages to its creator, which in turn should update the DOM.

You can pass data to and from the Web Worker using the postMessage function. Inside the Web Worker postMessage is a global function that accepts an object as its only argument. This will trigger the myWorker.onmessage callback function. Where the event.data property will be set to the object passed into postMessage. To pass data into the Web Worker, call the myWorker.postMessage function and pass in an object as its only argument. This will fire the global onmessage function inside of the Web Worker, and again event.data will be the object.

Objects that are passed through the postMessage infrastructure should serialization, meaning it does not contain functions or cyclical references. You may pass simple values such as Strings and Numbers, or more complex values such as Objects and Arrays. All values are serialized to JSON for transportation between threads.

The onerror callback function is fired when a runtime error occurs while the Web Worker is executing. The callback event has three properties: the error message, the offending filename, and the line number that through the error (lineno).

Additionally, web workers can be used to send IO requests using the XMLHttpRequest object, but the responseXML and channel properties are always null. You can also spawn sub Web Workers from inside of a running Web Worker to fork tasks. This can be particularly useful one machines that have multiple processors.

Theres more…

The issue with Web Workers are that they are not supported by all browsers. They are supported by FireFox 3.5, Safari 4, and Chrome. They are not supported by IE and so far IE has not announced supporting them in IE 9 either. However, just because they arent supported by every browsers, doesnt mean we shouldnt start using them. Developers just need to implement them in a way that is backwards compatible, only using Web Workers if available, and falling back to standard JavaScript.

I have not seen a wide use of Web Workers in mainstream applications yet, but I am hopeful it will happen soon. Probably the most applicable technology for leveraging Web Workers is in conjunction with the Canvas element. There can be a lot of number crunching required for 2d and 2.5d animations, whose behavior would be improved by leveraging Web Workers.

There are definitely other useful applications for Web Workers, feel free to leave your ideas in the comment section.

See also