First off, the idea with web workers is to be be able to do stuff on a webpage without blocking. On a web page everything is done in the same thread, so if something your doing take a while, it prevents everything else form working and can cause the page to freeze, in this example you can see that by hitting the red button, or running it in Internet Explorer versions older then 10. Hitting the green button executes that long script as a worker and thus the time keeps ticking.
The two main issues that seem to be keeping workers from being more widely used are:
- Internet Explorer
- Having to load the worker script as a separate file.
First, Internet Explorer doesn’t support workers until version 10, the one that just came out and nobody uses. This means that your almost definitely going to have people viewing on clients that don’t support workers.
You have to load the worker script from a separate file, now I can see the reasoning behind this restriction as it keeps the 2 contexts separated. But it introduces a couple of issues,
- Poly fills are much trickier (though I then found this polyfill right after I wrote that).
- Can’t use them with CDN hosted scripts, the worker script has to obey the same origin policy of the html page that it’s run on, but the script that’s calling it does not.
So my idea to deal with this is a library I’ve been writing called Communist.js (why the title, because it cares about the workers). It works around the pattern of write a function, create a new Communist with that function, then send the communist data and a callback, and the communist executes the function in the other thread and calls the callback with the result. If the client doesn’t support web workers it gets executed in thread by a function I call Socialist (Can you tell I wrote for a humor magazine in college?).
Under the hood, Communist is turning the function into a string, templating it with some code to handle message passing, and turning that string into a blob file, which we are then creating a blob URL out of the blob which we are using to make the worker. This is based on the “inline worker” example on the MDN page about using worker, but updated to take into account blob builder being deprecated. This method does have some drawbacks, notably you will get an error if your function references a variable defined outside the function.
Now Socialist ended up giving me much more grief, as I ended up having to recreated certain parts of the worker global object that acted subtly different there as opposed to when executed in the regular context. Notably setInterval which calls it’s it’s function with window as the context even when it’s called from a function with a different context.
So it still needs some work, but don’t hesitate to fork it on Github.
P.S. you may notice I decided to write it in CoffeeScript. Now why would I do that? My growing appreciation for CoffeeScript really deserves its own blog post but quickly:
- Indentation, my code is so much neater when it isn’t optional.
- Prototype as ::. I just think it looks cool.
- Class keyword, this makes much of the prototype mess much easier (and ironically means I never got to use :: in this library).