As far as I can tell, web workers need to be written in a separate JavaScript file, and called like this:
new Worker('longrunning.js')
I'm using the closure compiler to combine and minify all my JavaScript source code, and I'd rather not have to have my workers in separate files for distribution. Is there some way to do this?
new Worker(function() {
//Long-running work here
});
Given that first-class functions are so crucial to JavaScript, why does the standard way to do background work have to load a whole 'nother JavaScript file from the server?
You can create a single JavaScript file that is aware of its execution context and can act as both a parent script and a worker. Let's start off with a basic structure for a file like this:
As you can see, the script contains all code for both the parent's and the worker's point of view, checking if its own individual instance is a worker with
!document
. The somewhat unwieldyscript_path
computation is used to accurately calculate the script's path relative to the parent page, as the path supplied tonew Worker
is relative to the parent page, not the script.The html5rocks solution of embedding the web worker code in HTML is fairly horrible.
And a blob of escaped JavaScript-as-a-string is no better, not least because it complicates work-flow (Closure compiler can't operate on strings).
Personally I really like the toString methods, but @dan-man THAT regex!
My preferred approach:
Support is the intersection of these three tables:
This won't work for a SharedWorker however, because the URL must be an exact match, even if the optional 'name' parameter matches. For a SharedWorker, you'll need a separate JavaScript file.
2015 update - The ServiceWorker singularity arrives
Now there's an even more powerful way of solving this problem. Again, store the worker code as a function, (rather than a static string) and convert using .toString(), then insert the code into CacheStorage under a static URL of your choice.
There are two possible fall-backs. ObjectURL as above, or more seamlessly, put a real JavaScript file at /my_workers/worker1.js
Advantages of this approach are:
Using the
Blob
method, how about this for a worker factory:So you could use it like this...
EDIT:
I've just extended this idea further to make it easier to do cross-thread communication: bridged-worker.js.
EDIT 2:
The above link is to a gist I created. Someone else later turned it into an actual repo.
Taking Adria's response and putting it in a copy-pastable function which works with current Chrome and FF but not IE10 (worker from blob causes a security error).
And here's a working example http://jsfiddle.net/ubershmekel/YYzvr/
Web workers operate in entirely separate contexts as individual Program's.
This means that code cannot be moved from one context to another in object form, as they would then be able to reference objects via closures belonging to the other context.
This is especially crucial as ECMAScript is designed to be a single threaded language, and since web workers operate in separate threads, you would then have the risk of non-thread-safe operations being performed.
This again means that web workers need to be initialized with code in source form.
The spec from WHATWG says
but unfortunately it doesn't really explain why one couldn't have allowed passing a string with source code to the constructor.
a better to read way for a inline worker..