How to Use JavaScript Shared Web Workers in HTML5

    Craig Buckler
    Share

    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!