HTML5 Web Workers
- Creating a Web Worker
- Communicating With the Web Worker
- Web Worker Implementation
- Web Worker Live Example
- The Web Worker Sandbox
- Importing JavaScript in a Web Worker
- SharedWorker
- Creating a SharedWorker
- Connecting to a SharedWorker
- Sending Messages to a SharedWorker
- SharedWorker Implementation
- SharedWorker Live Example
Jakob Jenkov |
The Web Workers API makes it possible to execute a JavaScript file asynchronously and autonomously. A web worker is essentially a thread executing a JavaScript file. Thus, using web workers you can achieve multi threading in your web applications.
Creating a Web Worker
You create a web worker like this:
var worker = new Worker("http://jenkov.com/worker.js");
The string passed as parameter to the Worker() is the URL of the JavaScript file
to execute.
Communicating With the Web Worker
You communicate with the web worker using the HTML5 Messaging API, by posting messages to, and receiving messages from, the web worker. Here is an example:
var worker = new Worker("http://jenkov.com/worker.js");
worker.onmessage = function(event) {
alert("Reply: " + event.data);
}
worker.postMessage("Hello worker!");
First a Worker is created.
Second, an onmessage event listener function is set on the web worker.
This function is called when the worker sends messages back to the page that created it.
Third, a message is sent to the web worker using the worker.postMessage() function.
The web worker can respond like this:
this.onmessage = function(event) {
postMessage("Reply from web worker");
}
This code is part of the JavaScript file executed by the web worker. The this keyword
is a reference to the web worker instance itself. An onmessage event listener function
is added to the web worker. This is not the same onmessage listener as the page
creating the web worker added, even if both were added on the worker instance. The web worker
responds to the message using the postMessage().
Exchanging JSON
In the first implementations of web workers the browsers only allowed strings to be exchanged as messages.
You can encode a JSON object using the JSON.stringify() function and decode it again using the
JSON.parse() function.
However, recent implementations allow for exchange of values or JSON objects that can be handled by the structured clone algorithm.
Web Worker Implementation
Here is a full implementation of a web worker:
this.onmessage = function(event) {
postMessage("Reply from web worker");
}
//Implementation of web worker thread code
setInterval(function() { runEveryXSeconds() }, 5000);
function runEveryXSeconds() {
postMessage("Calling back at : " + new Date().getTime());
}
This web worker implementation listens for messages, as well as sends a message every 5 seconds to the page that started it.
Web Worker Live Example
Here you can execute the example code shown earlier. Click the button below to execute the example.
To stop the messages sent back every 5 seconds, hit refresh in the browser.
The Web Worker Sandbox
The web workers run in a kind of sandbox, meaning that the web worker has limited access to the features JavaScript normally has access to when executed in a browser.
A web worker does not have access to the DOM of the page that creates the web worker.
Here is a list of what a web worker can do inside the web worker JavaScript:
- Listen for messages, using the
onmessageevent listener function. - Send messages via the
postMessage()function. - Send AJAX requests using the XMLHttpRequest.
- Create timers using the
setTimeout()andsendInterval()functions. - Web Sockets
- Web SQL Databases
- Web Workers
- Import more scripts using
importScripts()
Importing JavaScript in a Web Worker
You can import JavaScript files for use in your web worker, using the importScripts()
function. This is a special function available in a web worker. Here is an example:
importScripts("myscript.js");
importScripts("script1.js", "script2.js");
You can load one or more scripts using the importScripts() function, as you can see
from the example above. The scripts are loaded synchronously, and executed one at a time.
SharedWorker
An ordinary web worker is only accessible by the page that created it. If you want to share a
web worker between multiple pages, you can use a SharedWorker. A SharedWorker
is accessible by all pages that are loaded from the same origin (domain).
Creating a SharedWorker
You create a SharedWorker like this:
var worker = new SharedWorker("shared-worker.js");
The string passed as parameter to the SharedWorker constructor is the URL
of the JavaScript the SharedWorker is going to execute.
All pages that create an instance of a SharedWorker with the same URL
passed as parameter, will essentially get a connection to the same SharedWorker
behind the scenes.
Connecting to a SharedWorker
A SharedWorker has a concept called ports through which the various pages
that reference the SharedWorker can communicate with it. The API is again
similar to the HTML5 Messaging API.
Here is an example of how to add a message listener to the port of a SharedWorker:
var worker = new SharedWorker("/html5/web-worker-shared.jsp");
worker.port.addEventListener("message",
function(event) {
alert(event.data);
}
, false
);
worker.port.start();
First at SharedWorker is created. Second, a message event listener function is
added to the SharedWorker's port. Third, the port is started. If you do not start
the port, you cannot send messages to the SharedWorker.
Sending Messages to a SharedWorker
Once the port is started and your page is listening for messages on the port, you can
send messages to the SharedWorker using the port.postMessage() function.
Here is an example:
worker.port.postMessage("First Message");
SharedWorker Implementation
A SharedWorker, like an ordinary web worker, needs an implementation in a JavaScript
file. Here is an example implementation:
var ports = [] ;
onconnect = function(event) {
var port = event.ports[0];
ports.push(port);
port.start();
port.addEventListener("message",
function(event) { listenForMessage(event, port); } );
}
listenForMessage = function (event, port) {
port.postMessage("Reply from SharedWorker to: " + event.data);
}
//Implementation of shared worker thread code
setInterval(function() { runEveryXSeconds() }, 5000);
function runEveryXSeconds() {
for(i = 0; i < ports.length; i++) {
ports[i].postMessage("Calling back at : "
+ new Date().getTime());
}
}
This implementation first creates an array for storing the ports of all the pages
that connects with the SharedWorker.
Second, an onconnect function is defined. This function is called
when a page connects to the SharedWorker.
The onconnect function first obtains the port to the connecting page, stores it in the
port array and then starts the port. If you do not start the port, you cannot receive messages from it.
Finally the onconnect function adds a message listener function to the port. Notice how
a new anonymous function is created for each page connecting. This anonymous function captures the port
to the connecting page and passes it as parameter to the listenForMessage() function called
from the anonymous function.
After the onconnect function is a definition of the event listening function listenForMessage()
This function simply responds to the port from which the message was received with a simple message.
The last part of this SharedWorker contains the implementation of the autonomous behaviour
this SharedWorker has. The setInterval() function is called to make the
runEveryXSeconds() execute every 5 seconds (5000 milliseconds).
The runEveryXSeconds() simply iterates all the connected ports and write a message to them.
A more advanced implementation could connect to a server and fetch data which could be distributed to
all the pages connected to the SharedWorker.
SharedWorker Live Example
Here is a live example of a SharedWorker. Start the SharedWorker
by clicking the button on the left. Send a message to the SharedWorker by
clicking on the button on the right.
| Tweet | |
Jakob Jenkov | |











