- Key Takeaways
- Web Worker Restrictions
- Web Worker Browser Support
- What is a Web Worker?
- Creating a Dedicated Web Worker
- Communicating With a Dedicated Web Worker
- Handling Dedicated Web Worker Errors
- Loading Further JavaScript Files
- Stopping a Dedicated Web Worker
- Frequently Asked Questions (FAQs) about JavaScript Threading and HTML5 Web Workers
Key Takeaways
- Web workers in JavaScript, one of the best features in browsers, allow developers to run ongoing processes in a separate thread, offering significant client-side performance gains. However, they operate independently of the browser UI thread and have some restrictions, such as no access to the DOM, global variables or JavaScript functions within the page.
- To create and communicate with a dedicated web worker, developers pass a JavaScript file name to a new instance of the Worker object and handle all communication through an event interface. The web page script passes a single data argument via the postMessage() method and receives one back via an onmessage event handler.
- Web workers are widely supported in modern browsers, but not in any version of Internet Explorer. They can use standard JavaScript data types, handle XMLHttpRequest (Ajax) calls, use timers, import other workers, and are ideal for time-consuming tasks such as analyzing large blocks of data, game AI logic, and ray-tracing.
Web Worker Restrictions
Web workers operate independently of the browser UI thread so they’re not able to access many of the features JavaScript developers know and love. The primary restriction is that web workers have no access to the DOM; they cannot read or modify the HTML document. In addition, you cannot access global variables or JavaScript functions within the page. Finally, access to some objects is restricted, e.g. window.location properties are read-only. However, web workers can use standard JavaScript data types, handle XMLHttpRequest (Ajax) calls, use timers and even import other workers. They are ideal for time-consuming tasks such as analyzing large blocks of data, game AI logic, ray-tracing, etc.Web Worker Browser Support
At the time of writing, all the recent editions of Firefox, Chrome, Safari and Opera support web workers to some extent. Guess which browser is missing? Unsurprisingly, web workers are not implemented in any version of Internet Explorer. Even IE9 does not offer support but I suspect/hope it will be implemented in the final release. Until that time, you have three options:- Forget about web workers for another year or two.
- Accept that your application will break in IE.
- Implement your own web worker shim which falls back to timer-based pseudo-threading or array processing. That may not be possible or advisable in all applications.
What is a Web Worker?
A web worker is a single JavaScript file loaded and executed in the background. There are two types:- Dedicated workers: these are linked to their creator (the script which loaded the worker).
- Shared workers: the allow any script from the same domain (somesite.com) to communicate with the worker.
Creating a Dedicated Web Worker
To create a dedicated web worker, you pass a JavaScript file name to a new instance of the Worker object:
var worker = new Worker("thread1.js");
Communicating With a Dedicated Web Worker
Since the web worker cannot access the DOM or execute functions within the page’s script, all communication is handled through an event interface. The web page script passes a single data argument via thepostMessage()
method and receives one back via an onmessage
event handler, e.g.
pagescript.js:
var worker = new Worker("thread1.js");
// receive messages from web worker
worker.onmessage = function(e) {
alert(e.data);
};
// send message to web worker
worker.postMessage("Jennifer");
The web worker script receives and sends data via it’s own onmessage
event handler and postMessage()
method accordingly:
thread1.js:
self.onmessage = function(e) {
self.postMessage("Hello " + e.data);
};
The message data can be a string, number, boolean, array, object, null or undefined. Data is always passed by value and serialized then de-serialized during the communication process.
Handling Dedicated Web Worker Errors
Web worker code is unlikely to be perfect, and logic errors could be caused by the data passed by the page script. Fortunately, errors can be caught using an onerror event handler. The handler event is passed an object with 3 properties:- filename: the name of the script which caused the error;
- lineno: the line number where the error occurred; and
- message: a description of the error.
worker.onerror = function(e) {
alert("Error in file: "+e.filename+"nline: "+e.lineno+"nDescription: "+e.message);
};
Loading Further JavaScript Files
One or more additional JavaScript libraries can be loaded within a web worker usingimportScripts()
, e.g.
importScripts("lib1.js", "lib2.js", "lib3.js");
Alternatively, you could load further web workers … but, I’d recommend keeping it simple until browsers catch up with your threading ambitions!
Stopping a Dedicated Web Worker
The web worker thread can be stopped using theclose()
method, e.g.
thread1.js:
self.onmessage = function(e) {
if (e.data == "STOP!") self.close();
};
This discards any tasks awaiting processing and prevents further events being queued.
That’s all you need to know about dedicated web workers. In my next post, we’ll discuss shared web workers — a more complex beast!
Frequently Asked Questions (FAQs) about JavaScript Threading and HTML5 Web Workers
What are the benefits of using Web Workers in JavaScript?
Web Workers in JavaScript are a powerful tool that allows developers to run scripts in the background, separate from the main execution thread of a web application. This means that complex and time-consuming operations can be performed without blocking the user interface, leading to a smoother and more responsive user experience. Web Workers can handle tasks such as computations, network requests, and I/O operations, freeing up the main thread to focus on user interactions and rendering.
How do I create a Web Worker?
Creating a Web Worker is straightforward. You simply need to create a new Worker object and pass the path to the JavaScript file that will run in the worker thread as an argument. Here’s an example:var worker = new Worker('worker.js');
In this example, ‘worker.js’ is the JavaScript file that will be executed in the worker thread.
Can Web Workers access the DOM?
No, Web Workers cannot directly access the Document Object Model (DOM). This is because they run in a separate context, isolated from the main thread. This design helps to prevent potential issues with concurrent access to DOM state. However, Web Workers can communicate with the main thread using the postMessage API and the onmessage event handler, allowing them to send data back and forth.
How do Web Workers communicate with the main thread?
Web Workers communicate with the main thread using a system of messages. The postMessage method is used to send messages from the worker to the main thread, and the onmessage event handler is used to receive these messages. Here’s an example:// In the main thread
var worker = new Worker('worker.js');
worker.onmessage = function(event) {
console.log('Received message from worker: ', event.data);
};
worker.postMessage('Hello, worker!');
// In worker.js
self.onmessage = function(event) {
console.log('Received message from main thread: ', event.data);
self.postMessage('Hello, main thread!');
};
What is the lifecycle of a Web Worker?
A Web Worker’s lifecycle begins when it is created using the Worker constructor. The worker then runs until it has completed its task, at which point it becomes idle. If the worker is no longer needed, it can be terminated using the terminate method. Alternatively, a worker can terminate itself by calling the close function.
Can Web Workers share data with each other?
Web Workers cannot directly share data with each other as they run in separate contexts. However, they can communicate with the main thread using the postMessage API and the onmessage event handler. The main thread can then relay messages between workers.
Are Web Workers supported in all browsers?
Web Workers are widely supported in modern browsers, including Chrome, Firefox, Safari, and Edge. However, they are not supported in Internet Explorer. You can check the current level of support on the Can I use website.
Can Web Workers use third-party libraries?
Yes, Web Workers can import scripts using the importScripts function. This allows them to use third-party libraries and other scripts. However, the scripts must be on the same domain as the worker, or on a domain that allows cross-origin requests.
How can I handle errors in a Web Worker?
Errors in a Web Worker can be handled using the onerror event handler. This will be triggered whenever an uncaught error occurs in the worker. Here’s an example:worker.onerror = function(event) {
console.error('Error in worker: ', event.message);
};
Can I use Web Workers with frameworks like React or Angular?
Yes, you can use Web Workers with JavaScript frameworks like React or Angular. However, because workers run in a separate context and cannot access the DOM, you will need to carefully consider how to structure your application to make effective use of them.
Craig is a freelance UK web consultant who built his first page for IE2.0 in 1995. Since that time he's been advocating standards, accessibility, and best-practice HTML5 techniques. He's created enterprise specifications, websites and online applications for companies and organisations including the UK Parliament, the European Parliament, the Department of Energy & Climate Change, Microsoft, and more. He's written more than 1,000 articles for SitePoint and you can find him @craigbuckler.