One of the biggest challenges that still exist for web developers today is how to create feature-rich web applications that are very responsive to users. One of the main issues is that JavaScript is a single-threaded environment, which means that multiple scripts cannot run at the same time.
You may have heard the term “blocking” or “non-blocking” with regard to JavaScript code. Unfortunately, JavaScript execution happens within a single thread. One of the most useful additions to HTML5 is the support for Web Workers. Web Workers will allow designing more responsive web applications than otherwise possible in the past.
Introduction to Web Workers
Web Workers are an application programming interface (API) specification that lets you create multiple JavaScript threads in the background. Normally in browsers, a single thread is created to handle all the JavaScript code.
Therefore JavaScript code is executed in that single thread. While your client is processing JavaScript code, it is possible that the page can appear to be unresponsive to the user until the process has been completed.
Web Workers alleviate this problem by letting you create multiple JavaScript threads that will run independently of each other. Web Workers ensure that the user can continue to interact with the page while your JavaScript code runs in the background.
Support for Web Workers
Web workers are supported in all major browsers, except Internet Explorer. Before you create any Web Worker objects, you should consider checking to see if your browser supports HTML5 Web Workers. The following example code can be used to check if your browser supports Web Workers.
<script>
if (typeof (Worker) !== "undefined") {
// Web Workers are supported
} else {
// No Web Worker support..
}
</script>
Creating a Web Worker
After you have successfully verified that the browser supports web workers, you can then proceed with the creation of one. In the following example, we will create a Web Worker that will increment its counter. We are using the setTimeout
method and have specified that the interval is 1000 milliseconds. Therefore the counter will increment every second.
While this is a simple example, you would generally implement this technique for JavaScript which is more elaborate and processor intensive. Keep in mind that the main benefit of a web worker is to not “block” or impact the user experience by running these processes in the background. The following code is placed in an external JavaScript file.
var x=0;
function counter() {
x=x+1;
postMessage(x);
setTimeout("counter()",1000);
}
counter();
Communicating with a Web Worker
In the previous example, you may have noticed the postMessage()
method. Communication between a web worker and the calling HTML page is done using an event model and the postMessage()
method. Depending on your browser/version, postMessage()
can accept either a string or JSON object as its single argument.
The latest versions of modern browsers support passing a JSON object. The following example will create a new Web Worker thread and execute the JavaScript code in the external file.
if(typeof(counterWorker)=="undefined") {
counterWorker=new Worker("counter.js");
}
Once we have created Workers we can send and receive messages. We need to add an event handler to handle these messages.
counterWorker.onmessage=function(event) {
document.getElementById("workerResults").innerHTML=event.data;
};
Terminate the Web Worker
Once a Web worker object is created, it will continue to listen for messages until it is terminated. To terminate a web worker, use the terminate()
method.
counterWorker.terminate();
Example
So let us put all of this code together in a working example.
<!DOCTYPE html>
<html>
<body>
<p>Current Count: <output id="counterResult"></output></p>
<button onclick="startWorker()">Start Web Worker</button>
<button onclick="stopWorker()">Stop Web Worker</button>
<br /><br />
<script>
var counterWorker;
function startWorker() {
if(typeof(Worker)!=="undefined") {
if(typeof(counterWorker)=="undefined") {
counterWorker=new Worker("counter.js");
}
counterWorker.onmessage = function (event) {
document.getElementById("counterResult").innerHTML=event.data;
};
} else {
document.getElementById("counterResult").innerHTML="Your browser does not support Web Workers.";
}
}
function stopWorker() {
counterWorker.terminate();
}
</script>
</body>
</html>