Using Web Workers and keeping support for IE9
Here's a simple tip to use web worker code; yet maintain support for IE9.
Introduction
Included in the HTML5 specification is a background worker type called a Web Worker. Even if you are developing an HTML5 based site, you still cannot fully use this because of IE9 which does not have support. On the mobile browser front, you'll need the latest iOS or Opera at the moment. See http://www.caniuse.com/#feat=webworkers for updated information.
Background
The concepts and implementations for Web Workers were already documented in two very good articles:
- http://www.codeproject.com/Articles/271571/Introduction-to-HTML5-Web-Workers-The-JavaScript-M
- http://www.codeproject.com/Articles/179106/Web-Workers-in-HTML5.aspx
This is not a tutorial on how to use them; it's a simple example of how to use them and not have to worry about browser support.
Using the code
A common method of this might be to check for worker support, and have two different code paths to run your task. Your task may be an HTTP request, image processing, or any kind of processor/network intensive method. In any case, I prefer to have only one code path when possible. This helps in debugging, and when changes are needed.
With that in mind, here's our simple HTML file. It calls a specific JavaScript function either in a worker (if possible) or without if not possible.
<!DOCTYPE html>
<html>
<head>
<title>Worker test</title>
<script src="worker.js"></script>
<script>
// Constructor for our object the worker will process.
function Foo(i) {
this.iLoopTo = i;
}
window.onload = function () {
// counting to a billion to slow us up
var f = new Foo(1000000000);
// If the bowser handles workers, use it.
if (window["Worker"]) {
// Create a worker, and assign the callback
var w = new Worker("worker.js");
w.onmessage = workerCallback;
w.postMessage(f);
}
else {
// Calling this in our own thread, NOT in a worker
countToNum(f);
}
}
function workerCallback(event) {
// If there's a data property, we came from a worker.
if (event.data) {
event = event.data;
}
document.getElementById("p1").innerHTML = event;
};
</script>
</head>
<body>
<p id="p1">Waiting for something to process...</p>
</body>
</html>
And, here's the corresponding worker.js file:
onmessage = countToNum;
function countToNum(event) {
var obj = event;
var isWorker = false;
// If we have a data property, assume this is a real worker
if (obj.data) {
obj = obj.data;
isWorker = true;
}
// Here's some code just to slow us down.
// Typically this could be a data load or other task.
var f = 0;
for (var i = 0; i < obj.iLoopTo; i++) {
f += 1;
}
// And post back to the DOM thread
if (isWorker) {
postMessage("Counted to " + f + " in a worker");
}
else {
workerCallback("Counted to " + f + " not in a worker");
}
}
Points of Interest
You'll notice that in IE9 the text on the page of "Waiting for something to process" never shows. The script takes off and IE becomes unresponsive for a few seconds while that happens. Then the final output shows up instead. There will be minor nuances like this. Also, the browser warning that a script is taking a long time would still occur here; but there's no way around that until your users update their browsers.