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
onmessage
event 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 |