Workers provide a simple means for web content to run scripts in background threads. Once created, a worker can send messages to the spawning task by posting messages to an event handler specified by the creator.
The worker thread can perform tasks without interfering with the user interface. In addition, they can perform I/O using XMLHttpRequest (although the responseXML and channel attributes are always null).
See Worker for reference documentation on workers; this article complements that one by offering examples and added details. For a list of functions available to workers, see Functions available to workers.
About thread safety
The Worker interface spawns real OS-level threads, and concurrency can cause interesting effects in your code if you aren't careful. However, in the case of web workers, the carefully controlled communication points with other threads means that it's actually very hard to cause concurrency problems. There's no access to non-thread safe components or the DOM and you have to pass specific data in and out of a thread through serialized objects. So you have to work really hard to cause problems in your code.
Spawning a worker
Creating a new worker is simple. All you need to do is call the Worker() constructor, specifying the URI of a script to execute in the worker thread, and, if you wish to be able to receive notifications from the worker, set the worker's onmessage property to an appropriate event handler function.
var myWorker = new Worker('my_worker.js');
myWorker.onmessage = function(event) {
print("Called back by the worker!\n");
};
Line 1 in this example creates and starts running the worker thread. Line 2 sets the onmessage handler for the worker to a function that is called when the worker calls its own postMessage() function.
Spawning subworkers
Workers may spawn more workers if they wish. So-called subworkers must be hosted within the same origin as the parent page. Also, the URIs for subworkers are resolved relative to the parent worker's location rather than that of the owning page. This makes it easier for workers to keep track of where their dependencies are.
Timeouts and intervals
Workers can use timeouts and intervals just like the main thread can. This can be useful, for example, if you want to have your worker thread run code periodically instead of nonstop.
See setTimeout(), clearTimeout(), setInterval(), and clearInterval() for details.
Terminating a worker
If you need to immediately terminate a running worker, you can do so by calling the worker's terminate() method:
myWorker.terminate();
The worker thread is killed immediately without an opportunity to complete its operations or clean up after itself.
Workers may close themselves by calling their own
nsIWorkerScope.close()
method.
Handling errors
When a runtime error occurs in worker, its onerror event handler is called. It receives an event named error which implements the ErrorEvent interface. The event doesn't bubble and is cancelable; to prevent the default action from taking place, the worker can call the error event's preventDefault() method.
The error event has the following three fields that are of interest:
message- A human-readable error message.
filename- The name of the script file in which the error occurred.
lineno- The line number of the script file on which the error occurred.
Accessing the navigator object
Workers may access the navigator object, which is available within their scope. It contains the following strings which can be used to identify the browser, just as can be done from normal scripts:
appNameappVersionplatformuserAgent
Importing scripts and libraries
Worker threads have access to a global function, importScripts(), which lets them import scripts or libraries into their scope. It accepts as parameters zero or more URIs to resources to import; all of the following examples are valid:
importScripts(); /* imports nothing */
importScripts('foo.js'); /* imports just "foo.js" */
importScripts('foo.js', 'bar.js'); /* imports two scripts */
Firefox loads each listed script, then runs them to allow them to initialize themselves. Any global objects from each script may then be used by the worker.
importScripts(). This is done synchronously; importScripts() does not return until all the scripts have been loaded and executed.Examples
This section provides several examples of how to use DOM workers.
Performing computations in the background
One way workers are useful is to allow your code to perform processor-intensive calculations without blocking the user interface thread. In this example, a worker is used to calculate Fibonacci numbers.
The JavaScript code
The following JavaScript code is stored in the "fibonacci.js" file referenced by the HTML in the next section.
var results = [];
function resultReceiver(event) {
results.push(parseInt(event.data));
if (results.length == 2) {
postMessage(results[0] + results[1]);
}
}
function errorReceiver(event) {
throw event.data;
}
onmessage = function(event) {
var n = parseInt(event.data);
if (n == 0 || n == 1) {
postMessage(n);
return;
}
for (var i = 1; i <= 2; i++) {
var worker = new Worker("fibonacci.js");
worker.onmessage = resultReceiver;
worker.onerror = errorReceiver;
worker.postMessage(n - i);
}
};
The worker sets the property onmessage to a function which will receive messages sent when the worker object's postMessage() is called. (Note that this differs from defining a global variable of that name, or defining a function with that name. var onmessage and function onmessage will define global properties with those names, but they will not register the function to receive messages sent by the web page that created the worker.) This starts the recursion, spawning new copies of itself to handle each iteration of the calculation.
The HTML code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<title>Test threads fibonacci</title>
<body>
<div id="result"></div>
<script language="javascript">
var worker = new Worker("fibonacci.js");
worker.onmessage = function(event) {
document.getElementById("result").textContent = event.data;
dump("Got: " + event.data + "\n");
};
worker.onerror = function(error) {
dump("Worker error: " + error.message + "\n");
throw error;
};
worker.postMessage("5");
</script>
</body>
</html>
The web page creates a div element with the ID result, which gets used to display the result, then spawns the worker. After spawning the worker, the onmessage handler is configured to display the results by setting the contents of the div element, and the onerror handler is set to dump the error message.
Finally, a message is sent to the worker to start it.
Performing web I/O in the background
You can find an example of this in the article Using workers in extensions.
Dividing tasks among multiple workers
As multi-core computers become increasingly common, it's often useful to divide computationally complex tasks among multiple workers, which may then perform those tasks on multiple-processor cores.
example coming soon
Creating workers from within workers
The Fibonacci example shown previously demonstrates that workers can in fact spawn additional workers. This makes it easy to create recursive routines.
Sending objects to workers
You can safely pass objects in and out of workers using the postMessage() method; objects are automatically converted to JSON internally.
onmessage = function(e) {
postMessage(e.data);
};
Browser compatibility
| Browser | Basic Support | SharedWorker Support | Notes |
|---|---|---|---|
| Internet Explorer | --- | --- | |
| Firefox (Gecko) | 3.5 (1.9.1) | --- | |
| Opera | 10.60 | 10.60 | |
| Chrome | 3 | 5 | |
| Safari | 4 | 5 |

