HTML5 Web Workers significantly minimize the limitations imposed by JavaScript’s single-threaded nature, allowing you to keep the browser responsive.
HTML5 Web Workers significantly minimize the limitations imposed by JavaScript’s single-threaded nature, allowing you to keep the browser responsive.
When folks express their excitement about HTML5, the discussion is usually focused around features such as the AUDIO / VIDEO tags, Geolocation, or maybe improved semantics. These are all super cool, as are many other features that are part of (or associated with) the HTML5 specification. But, it often amazes me how little attention is given to Web Workers. In my opinion, the addition of Web Workers is a big deal.
This article will be presented in three parts:
Part I : Making the Case for Web Workers
Part II: A Simple Web Worker
Part III: Multiple Web Workers
Part I : Making the Case for Web Workers
JavaScript is a single-threaded technology. Only one thing can be done at a time.
Period. This is fine at first, but when JavaScript is doing any heavy-lifting, it can lock up the browser. Locking up the browser is bad, very bad. This is like a waiter serving your food late, and then spilling it on you. Regardless of how apologetic the waiter may be, you are not likely to tell your friends how great that restaurant is. As a web developer, all you need to do is lock up the browser once and you can be sure that the user is never (ever) going to tell their friends anything good about the page they were just viewing (and by association, the whole site gets a bad rap). They will not “like” it, tweet it, “plus-one” it, “pin” it, “dig” it or…. ok, you get the point: Don’t lock up the browser.
Number-crunching is probably the most challenging context. While all modern browsers have made great strides with regard to the speed of their JavaScript engines, heavy-duty calculations can still take time.. sometimes a few seconds. Unfortunately, a few seconds is out of the question. Many consider 100 milliseconds to be the limit; i.e. if a synchronous piece of code needs more than 100 milliseconds to return then that code probably needs some more attention.
HTML5 Web Workers allow you to execute JavaScript in a different thread than the one that the browser is running in. This is a big win. It means that in certain cases, your multi-second number-crunching code can be handed off to a Web Worker, and the browser can remain happy, peppy and bursting with love.
Did you notice the words: “…in certain cases” ? There are some limitations to how you can use Web Workers. It is far from a free-for-all. For example, you cannot access the Window, Document or Parent objects. Heavy DOM manipulation is out. At first glance, this may seem like a drawback. But as you can imagine, providing access to the DOM from more than one thread immediately complicates things in a way that is not good.
The key to leveraging the power of Web Workers is hinted at by its very name “worker.” Think of this feature as a calculator (or many calculators), that can be sent off to do some “work”, and then report back when done. I won’t go too crazy on the details here, there are many web-based resources that can provide an in-depth view of Web Workers. I’ve listed a few at the end of this article.
To make the case for Web Workers, let’s consider the following code example:
Example # 1
1 2 3 4 5 6 7 8 9 10 11 |
var crunch = function(){ var tStart = Number( new Date() ); while( (tStart + 5000) > Number(new Date())){ //i'm only sleeping }; alert("I'm done!"); }; crunch(); |
In Example # 1, we have a function that essentially “sleeps” for five seconds. If you run this code in your JavaScript console, it will lock up the browser for five seconds. Nasty business. We will use this code extensively throughout Parts I, II and III of this article. Every time you see this function referenced, just imagine that it is crunching some numbers (i.e where you see “I’m only sleeping”). The key point here is that a function that would need a few seconds to do some resource-intensive work, would behave in exactly the same way: it would lock up the browser.
Example # 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var crunch = function($el){ var randomNum = (Math.floor(Math.random() * 5) + 1), randomNumMilliseconds = (randomNum * 1000), tStart = Number( new Date() ); while( (tStart + randomNumMilliseconds) > Number(new Date())){ //i'm only sleeping } $el.removeClass('crunching'); $el.html('<p class="done">I\'m done.<br />It took me: ' + randomNum + ' seconds.</p>'); $('.hint').fadeIn(1000); }; |
in Example # 2, we have expanded the crunch() function so that it “sleeps” for a random number amount of time, up to five seconds. This makes the function feel a bit more “real world” in that the amount of time the function takes to “crunch” will vary a bit.
Click here to see a full working example of our “crunch” function in action: http://examples.kevinchisholm.com/javascript/web-workers/basic/example-1.php
In the example page, when you clicked “Crunch some numbers”, the browser locked up. If you tried to resize the box by clicking the “Re-Size Box” button, not only did nothing happen, but you probably got the “wait” cursor (this behavior varies from browser to browser). I intentionally used an Ajax loader gif to illustrate this: the gif’s animation is frozen during the numbers crunching. Once the “crunch” function has completed, it updates us with a message which tells us how long it took, and the browser is responsive again.
This is the “waiter spilling food on you” scenario. And it is not good.
In Part II, we will dive into Web Workers and learn how that technology can help us to pass off our number crunching work to a different thread, and keep the browser responsive at all times.
Summary
In this article we introduced the concept of Web Workers. We discussed the single-threaded nature of JavaScript and how it poses a challenge when it comes to resource-intensive work. We made our case with an example of a simple function that will render the browser unresponsive.
Helpful Links for HTML5 Web Workers
http://www.w3.org/TR/2009/WD-workers-20091029/
http://www.whatwg.org/specs/web-apps/current-work/multipage/workers.html