Cross-Platform Javascript WebWorker

By on 7/24/2009

If you’ve been keeping up with the new developments in the web world, no doubt you’ve heard about Web Workers.  A new technology for browsers that will let you take advantage of the client’s true multi-threading capabilities.  Currently, it’s only supported in Firefox 3.5, Safari 4, and some of the latest nightly Chrome builds.

I of course am very excited that the platform is moving ahead.  However, I am disheartened by the fact that it will take *ages* for the majority of the population to move to a browser that supports this feature.  So naturally started thinking about how I might be able to take advantage of this new feature, while still supporting older browsers.

Below you will find a relatively small script that will conditionally declare the Worker class if it’s not currently declared.  I tested it and it worked in IE8 in addition to Chrome (not the nightly with worker support), and of course FireFox 3.5, where it executes using the new feature rather than the wrapper.

please note: This code has a small dependency on jQuery to do the ajax call.  It should be pretty easy to substitute that with another framework's analogous feature if you so prefer.

The Worker Class

if (!Worker) { function Worker(path) { function InternalWorker(p) { this.onmessage = function(m) { if (trace) trace('received ' + m); };

$.get(p, function(data) { setTimeout(function() { eval(data); }, 1); }); }

var iworker = new InternalWorker(path);

function postMessage(m) { setTimeout(function() { iworker.onmessage({ data: m }) }, 1); }

return iworker; } }

The Usage

Once you’ve included the above script, you can use it as such:
<script> var worker = new Worker('Scripts/worker.js'); worker.onmessage = function(event) { $("#result").text(event.data); }; </script>

<div id="result"></div>

The Worker Script

The file mentioned above (Scripts/worker.js) is defined in my sample as follows:
postMessage("this is from the web worker");
I know, simple … all it does is post a message back to the main gui thread.

How it Works

The premise is very simple. If we need to fall back to manually supporting the feature on a downlevel browser, then we take the path to the script file which is passed into the constructor and download the contents of it using the $.get method.  We take that and use the setTimeout method to execute said script using the eval method.

This is of course not production-ready code. More of a proof of concept as I’ve only implemented the basic execution of the remote script, and passing messages back to the client.  If you actually try to do some heavy computation, the main thread will obviously get bogged down.  This will of course prompt IE to ask the user if they want to cancel the script.

However, I still see some value in being able to code using this API on all browsers.  The concept of message passing forces you to have clearly defined boundaries between functionality.  If your DOM modifying code can only talk to the validation functionality using messages, there’s a much higher chance that your code will be easy to maintain.

Please let me know if anyone is interested in further development of this little wrapper.  I’d like to collaborate on it and perhaps release a more fully featured and minified version on codeplex.

Thanks!

See more in the archives