Did you know you can multithread in JavaScript?
And it's really easy, too. Are you making a HTML5 game and need to build a random map or doubling pixels? Are you fetching a huge JSON request? Introducing Web Workers!
Dedicated Web 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.
https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers
TL;DR: Web Workers are awesome, go use them.
In the age of HTML5 apps, it's really important to provide a snappy and responsive UI. This idea dies quickly when you are doing heavy operations in JavaScript and might end up blocking interactions, resulting in a bad user experience. Web Workers introduce a way for you to do those operations on a different thread (and maybe even on a different CPU core) without blocking the UI thread!
Before we dig down in code, I want you to check out this test by Microsoft showcasing the performance of web workers: http://ie.microsoft.com/testdrive/HTML5/WebWorkerTest262/
var url = 'http://bigcontentprovider.com/hugejsonfile';
Let's create a function utlizing a web worker to import and parse a JSONP file
var f = '(function() {
send = function(e) {
// Send something to the main thread
postMessage(e);
// Close the worker gracefully, letting it clean up
// after itself
self.close();
};
// Import the JSONP file. Remember, this is a JSONP request,
// so the script we are fetching will execute itself
// after load using the specified callback function
importScripts("' + url + '?format=json&callback=send");
})();';
Web Workers normally accept files as arguments when creating one, so we'll need to create a Blob, a file impersonator. Read more about that here: https://developer.mozilla.org/en-US/docs/Web/API/Blob
// Using the stringed function f from above, we are creating
// a file like object
var _blob = new Blob([f], { type: 'text/javascript' });
This is where the magic happens. We're starting a new worker with the script I wrote above using window.URL.createObjectURL, a function that creates an object URL that we're using in place of a file name. Read more here: https://developer.mozilla.org/en-US/docs/Web/API/window.URL.createObjectURL
// To add webkit support, replace window.URL with
// (window.webkitURL || window.URL)
_worker = new Worker(window.URL.createObjectURL(_blob));
If you already have a script file you'd like to run, you'd specify the file path as a string, just like this:
_worker = new Worker('file.js');
To react to anything the worker does and sends us, we'll need to listen for events in the main thread. Here we'll log the event and the event data, which, in this case, is the parsed JSON object.
_worker.onmessage = function(e) { console.log(e, e.data) };
// We will also want to be notified if the worker runs into trouble
_worker.onerror = function(e) { console.log('Error:', e) };
// Start the worker!
_worker.postMessage();
That was easy wasn't it? Browser support is fairly good, too (http://caniuse.com/#search=web%20workers). If someone is using an older browser, you can just load the script to the main thread instead. Using a web worker has some limitations, but make perfect sense:
Workers do NOT have access to:
- The DOM (it's not thread-safe)
- The window object
- The document object
- The parent object
http://www.html5rocks.com/en/tutorials/workers/basics/
Now go out there and create non-sluggish web apps!
Written by Thomas Lindstrøm
Related protips
4 Responses
Nice read! Very well written... just posted something similar ... seems like you had been first :D Well played... well played.... always good to share the word of awesome new web features. :)
Thanks! Haha, yeah, I stumbled upon this while searching for performance tips in JavaScript, and I was stunned to see that this gem of a tool somehow has slipped right under my nose. I love the idea of multiple threads in JavaScript and I also wanted everyone else to know about it, and start using them - because web workers are simply too good to pass up.
nice :)
Theres a really useful Web Workers library that simplifies things: ParallelJS