A lot has been said about JavaScript Workers, particularly lately with the adoption of the Service Worker. I'm going to give a short breakdown of the difference between Web Workers and Service Workers, and why you would use them.
First of all, what is a JavaScript Worker?
A worker is a script that runs in a thread separate from the main thread in the browser. This means you can run code without blocking (and avoid that nasty jumping cursor during heavy computation). Workers are not meant for UI updates and do not have access to the DOM.
Web Workers
Web Workers have been around for a quite a while now. They don't have all the fancy capabilities of Service Workers, but when you need to offload heavy work to a separate thread they are the way to go.
Here is an example where we simply ask our worker to add two numbers together:
// webworker.js
self.onmessage = event => { // listen for messages from the main thread
console.log('Worker received event from main thread..');
const result = event.data.firstNum + event.data.secondNum;
self.postMessage(result);
};
Then in our main.js
(which we can reference from our html):
// main.js
const worker = new Worker('webworker.js'); // create our worker
worker.postMessage({ firstNum: 4, secondNum: 6 }); // post a message to our worker
worker.onmessage = event => { // listen for events from the worker
console.log(`Result is: ${event.data}`);
};
Now we've offloaded some work to our worker. This is obviously a trivial example, but this can be used effectively for say, syntax highlighting an online TypeScript editor.
Web Workers are supported in every major, non-dinosaur-era browser.
Service Workers
Service Workers offer a lot more functionality for creating Progressive Web Apps which give a great experience for offline users or users with slow internet connections. The Service Worker can be used as a proxy for network events, allowing us to cache resources for offline use.
The basic steps are as follows:
Register and install the Service Worker.
On a network request, check the cache.
If there is a hit, return the cached content.
// serviceworker.js
// Listen for install event
this.addEventListener('install', event => {
event.waitUntil(
// wait for the cache to be retrieved
caches
.open('resources') // Open a cache called 'resources'
.then(cache => cache.addAll(['/styles.css', '/image.png'])) // Cache files for later retrieval
);
});
// Listen for network requests
this.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request) // Respond with the cached content
);
});
...then we just need to register our worker with the browser:
// main.js
if ('serviceWorker' in navigator) { // Check browser support first
navigator.serviceWorker.register('/serviceworker.js');
}
In reality, you'll probably want more intelligent cache handling, but this is a start!
Support for Service Workers is relatively good among modern browsers, but not entirely up-to-date as of yet. You can find which browsers currenly support Service Workers over here.
In conclusion
Use a Web Worker for heavy computation on the client. Use a Service Worker for offline capabilities like intercepting network requests, as well as other fun stuff like push notifications and synchronization of content in the background.