How to Use JavaScript Shared Web Workers in HTML5
We recently discussed JavaScript web workers with reference to the “dedicated” variety. If you’ve not read it yet, I suggest you do that first — this article builds on the same concepts.
Web Workers in a Nutshell
A web worker is a single JavaScript file loaded and executed in the background on a separate thread. Dedicated web workers are linked to their creator (the script which loaded the worker). Shared web workers allow any number of scripts to communicate with a single worker.
Shared web workers adhere to the same rules as their dedicated counterparts: no DOM, document or page script access, and limited read-only permission to most window properties. In addition, page scripts may only communicate with shared web workers from the same origin/domain (somesite.com).
Currently, shared web workers are supported in Chrome, Safari and Opera. Firefox 4 and IE9 support may arrive, but don’t bet on it. Shared workers may save resources but they add an extra level of complexity. Expect a few issues, e.g.,
- DOM2 events (addEventListener) handlers appear to be the most reliable implementation.
- You’ll almost certainly encounter browser-specific quirks and debugging is difficult. The following code works in the latest version of Chrome, but don’t assume it’ll work in Safari or Opera.
Creating a Shared Web Worker
To create a shared web worker, you pass a JavaScript file name to a new instance of the SharedWorker object:
var worker = new SharedWorker("jsworker.js");
Communicating with a Shared Web Worker
Any of your page scripts can communicate with the shared web worker. Unlike dedicated web workers, you must communicate via a ‘port’ object and attach a message event handler. In addition, you must call the port’s start()
method before using the first postMessage()
:
pagescript.js:
var worker = new SharedWorker("jsworker.js");
worker.port.addEventListener("message", function(e) {
alert(e.data);
}, false);
worker.port.start();
// post a message to the shared web worker
worker.port.postMessage("Alyssa");
When the web worker script receives the first message from a script, it must attach an event handler to the active port. Under most circumstances, the handler will run its own postMessage()
method to return a message to the calling code. Finally, the port’s start()
method must also be executed to enable messaging:
jsworker.js:
var connections = 0; // count active connections
self.addEventListener("connect", function (e) {
var port = e.ports[0];
connections++;
port.addEventListener("message", function (e) {
port.postMessage("Hello " + e.data + " (port #" + connections + ")");
}, false);
port.start();
}, false);
Like their dedicated siblings, shared web workers can:
- load further scripts with
importScripts()
- attach error handlers, and
- run the
port.close()
method to prevent further communication on a specific port.
Shared web workers probably won’t be a viable technology for a couple of years, but they raise exciting opportunities for the future of JavaScript development. Let’s hope browser vendors can supply a few decent tracing and debugging tools!